Import pin-project 1.0.12 upstream upstream/1.0.12
authorRoy7Kim <myoungwoon.kim@samsung.com>
Mon, 20 Mar 2023 04:35:04 +0000 (13:35 +0900)
committerRoy7Kim <myoungwoon.kim@samsung.com>
Mon, 20 Mar 2023 04:35:04 +0000 (13:35 +0900)
207 files changed:
.cargo_vcs_info.json [new file with mode: 0644]
CHANGELOG.md [new file with mode: 0644]
Cargo.lock [new file with mode: 0644]
Cargo.toml [new file with mode: 0644]
Cargo.toml.orig [new file with mode: 0644]
LICENSE-APACHE [new file with mode: 0644]
LICENSE-MIT [new file with mode: 0644]
README.md [new file with mode: 0644]
examples/README.md [new file with mode: 0644]
examples/enum-default-expanded.rs [new file with mode: 0644]
examples/enum-default.rs [new file with mode: 0644]
examples/not_unpin-expanded.rs [new file with mode: 0644]
examples/not_unpin.rs [new file with mode: 0644]
examples/pinned_drop-expanded.rs [new file with mode: 0644]
examples/pinned_drop.rs [new file with mode: 0644]
examples/project_replace-expanded.rs [new file with mode: 0644]
examples/project_replace.rs [new file with mode: 0644]
examples/struct-default-expanded.rs [new file with mode: 0644]
examples/struct-default.rs [new file with mode: 0644]
examples/unsafe_unpin-expanded.rs [new file with mode: 0644]
examples/unsafe_unpin.rs [new file with mode: 0644]
src/lib.rs [new file with mode: 0644]
tests/README.md [new file with mode: 0644]
tests/auxiliary/mod.rs [new file with mode: 0644]
tests/cfg.rs [new file with mode: 0644]
tests/compiletest.rs [new file with mode: 0644]
tests/drop_order.rs [new file with mode: 0644]
tests/expand/default/enum.expanded.rs [new file with mode: 0644]
tests/expand/default/enum.rs [new file with mode: 0644]
tests/expand/default/struct.expanded.rs [new file with mode: 0644]
tests/expand/default/struct.rs [new file with mode: 0644]
tests/expand/default/tuple_struct.expanded.rs [new file with mode: 0644]
tests/expand/default/tuple_struct.rs [new file with mode: 0644]
tests/expand/multifields/enum.expanded.rs [new file with mode: 0644]
tests/expand/multifields/enum.rs [new file with mode: 0644]
tests/expand/multifields/struct.expanded.rs [new file with mode: 0644]
tests/expand/multifields/struct.rs [new file with mode: 0644]
tests/expand/multifields/tuple_struct.expanded.rs [new file with mode: 0644]
tests/expand/multifields/tuple_struct.rs [new file with mode: 0644]
tests/expand/naming/enum-all.expanded.rs [new file with mode: 0644]
tests/expand/naming/enum-all.rs [new file with mode: 0644]
tests/expand/naming/enum-mut.expanded.rs [new file with mode: 0644]
tests/expand/naming/enum-mut.rs [new file with mode: 0644]
tests/expand/naming/enum-none.expanded.rs [new file with mode: 0644]
tests/expand/naming/enum-none.rs [new file with mode: 0644]
tests/expand/naming/enum-own.expanded.rs [new file with mode: 0644]
tests/expand/naming/enum-own.rs [new file with mode: 0644]
tests/expand/naming/enum-ref.expanded.rs [new file with mode: 0644]
tests/expand/naming/enum-ref.rs [new file with mode: 0644]
tests/expand/naming/struct-all.expanded.rs [new file with mode: 0644]
tests/expand/naming/struct-all.rs [new file with mode: 0644]
tests/expand/naming/struct-mut.expanded.rs [new file with mode: 0644]
tests/expand/naming/struct-mut.rs [new file with mode: 0644]
tests/expand/naming/struct-none.expanded.rs [new file with mode: 0644]
tests/expand/naming/struct-none.rs [new file with mode: 0644]
tests/expand/naming/struct-own.expanded.rs [new file with mode: 0644]
tests/expand/naming/struct-own.rs [new file with mode: 0644]
tests/expand/naming/struct-ref.expanded.rs [new file with mode: 0644]
tests/expand/naming/struct-ref.rs [new file with mode: 0644]
tests/expand/naming/tuple_struct-all.expanded.rs [new file with mode: 0644]
tests/expand/naming/tuple_struct-all.rs [new file with mode: 0644]
tests/expand/naming/tuple_struct-mut.expanded.rs [new file with mode: 0644]
tests/expand/naming/tuple_struct-mut.rs [new file with mode: 0644]
tests/expand/naming/tuple_struct-none.expanded.rs [new file with mode: 0644]
tests/expand/naming/tuple_struct-none.rs [new file with mode: 0644]
tests/expand/naming/tuple_struct-own.expanded.rs [new file with mode: 0644]
tests/expand/naming/tuple_struct-own.rs [new file with mode: 0644]
tests/expand/naming/tuple_struct-ref.expanded.rs [new file with mode: 0644]
tests/expand/naming/tuple_struct-ref.rs [new file with mode: 0644]
tests/expand/not_unpin/enum.expanded.rs [new file with mode: 0644]
tests/expand/not_unpin/enum.rs [new file with mode: 0644]
tests/expand/not_unpin/struct.expanded.rs [new file with mode: 0644]
tests/expand/not_unpin/struct.rs [new file with mode: 0644]
tests/expand/not_unpin/tuple_struct.expanded.rs [new file with mode: 0644]
tests/expand/not_unpin/tuple_struct.rs [new file with mode: 0644]
tests/expand/pinned_drop/enum.expanded.rs [new file with mode: 0644]
tests/expand/pinned_drop/enum.rs [new file with mode: 0644]
tests/expand/pinned_drop/struct.expanded.rs [new file with mode: 0644]
tests/expand/pinned_drop/struct.rs [new file with mode: 0644]
tests/expand/pinned_drop/tuple_struct.expanded.rs [new file with mode: 0644]
tests/expand/pinned_drop/tuple_struct.rs [new file with mode: 0644]
tests/expand/project_replace/enum.expanded.rs [new file with mode: 0644]
tests/expand/project_replace/enum.rs [new file with mode: 0644]
tests/expand/project_replace/struct.expanded.rs [new file with mode: 0644]
tests/expand/project_replace/struct.rs [new file with mode: 0644]
tests/expand/project_replace/tuple_struct.expanded.rs [new file with mode: 0644]
tests/expand/project_replace/tuple_struct.rs [new file with mode: 0644]
tests/expand/pub/enum.expanded.rs [new file with mode: 0644]
tests/expand/pub/enum.rs [new file with mode: 0644]
tests/expand/pub/struct.expanded.rs [new file with mode: 0644]
tests/expand/pub/struct.rs [new file with mode: 0644]
tests/expand/pub/tuple_struct.expanded.rs [new file with mode: 0644]
tests/expand/pub/tuple_struct.rs [new file with mode: 0644]
tests/expand/unsafe_unpin/enum.expanded.rs [new file with mode: 0644]
tests/expand/unsafe_unpin/enum.rs [new file with mode: 0644]
tests/expand/unsafe_unpin/struct.expanded.rs [new file with mode: 0644]
tests/expand/unsafe_unpin/struct.rs [new file with mode: 0644]
tests/expand/unsafe_unpin/tuple_struct.expanded.rs [new file with mode: 0644]
tests/expand/unsafe_unpin/tuple_struct.rs [new file with mode: 0644]
tests/expandtest.rs [new file with mode: 0644]
tests/include/basic-safe-part.rs [new file with mode: 0644]
tests/include/basic.rs [new file with mode: 0644]
tests/lint.rs [new file with mode: 0644]
tests/pin_project.rs [new file with mode: 0644]
tests/pinned_drop.rs [new file with mode: 0644]
tests/proper_unpin.rs [new file with mode: 0644]
tests/repr_packed.rs [new file with mode: 0644]
tests/ui/cfg/cfg_attr-resolve.rs [new file with mode: 0644]
tests/ui/cfg/cfg_attr-resolve.stderr [new file with mode: 0644]
tests/ui/cfg/cfg_attr-type-mismatch.rs [new file with mode: 0644]
tests/ui/cfg/cfg_attr-type-mismatch.stderr [new file with mode: 0644]
tests/ui/cfg/packed_sneaky-span-issue-1.rs [new file with mode: 0644]
tests/ui/cfg/packed_sneaky-span-issue-1.stderr [new file with mode: 0644]
tests/ui/cfg/packed_sneaky-span-issue-2.rs [new file with mode: 0644]
tests/ui/cfg/packed_sneaky-span-issue-2.stderr [new file with mode: 0644]
tests/ui/cfg/packed_sneaky.rs [new file with mode: 0644]
tests/ui/cfg/packed_sneaky.stderr [new file with mode: 0644]
tests/ui/cfg/unsupported.rs [new file with mode: 0644]
tests/ui/cfg/unsupported.stderr [new file with mode: 0644]
tests/ui/not_unpin/conflict-unpin.rs [new file with mode: 0644]
tests/ui/not_unpin/conflict-unpin.stderr [new file with mode: 0644]
tests/ui/not_unpin/impl-unsafe-unpin.rs [new file with mode: 0644]
tests/ui/not_unpin/impl-unsafe-unpin.stderr [new file with mode: 0644]
tests/ui/pin_project/add-attr-to-struct.rs [new file with mode: 0644]
tests/ui/pin_project/add-attr-to-struct.stderr [new file with mode: 0644]
tests/ui/pin_project/add-pinned-field.rs [new file with mode: 0644]
tests/ui/pin_project/add-pinned-field.stderr [new file with mode: 0644]
tests/ui/pin_project/conflict-drop.rs [new file with mode: 0644]
tests/ui/pin_project/conflict-drop.stderr [new file with mode: 0644]
tests/ui/pin_project/conflict-unpin.rs [new file with mode: 0644]
tests/ui/pin_project/conflict-unpin.stderr [new file with mode: 0644]
tests/ui/pin_project/impl-unsafe-unpin.rs [new file with mode: 0644]
tests/ui/pin_project/impl-unsafe-unpin.stderr [new file with mode: 0644]
tests/ui/pin_project/import_unnamed.rs [new file with mode: 0644]
tests/ui/pin_project/import_unnamed.stderr [new file with mode: 0644]
tests/ui/pin_project/invalid.rs [new file with mode: 0644]
tests/ui/pin_project/invalid.stderr [new file with mode: 0644]
tests/ui/pin_project/overlapping_unpin_struct.rs [new file with mode: 0644]
tests/ui/pin_project/overlapping_unpin_struct.stderr [new file with mode: 0644]
tests/ui/pin_project/override-priv-mod.rs [new file with mode: 0644]
tests/ui/pin_project/override-priv-mod.stderr [new file with mode: 0644]
tests/ui/pin_project/packed-enum.rs [new file with mode: 0644]
tests/ui/pin_project/packed-enum.stderr [new file with mode: 0644]
tests/ui/pin_project/packed-name-value.rs [new file with mode: 0644]
tests/ui/pin_project/packed-name-value.stderr [new file with mode: 0644]
tests/ui/pin_project/packed.rs [new file with mode: 0644]
tests/ui/pin_project/packed.stderr [new file with mode: 0644]
tests/ui/pin_project/packed_sneaky-1.rs [new file with mode: 0644]
tests/ui/pin_project/packed_sneaky-1.stderr [new file with mode: 0644]
tests/ui/pin_project/packed_sneaky-2.rs [new file with mode: 0644]
tests/ui/pin_project/packed_sneaky-2.stderr [new file with mode: 0644]
tests/ui/pin_project/packed_sneaky-3.rs [new file with mode: 0644]
tests/ui/pin_project/packed_sneaky-3.stderr [new file with mode: 0644]
tests/ui/pin_project/packed_sneaky-4.rs [new file with mode: 0644]
tests/ui/pin_project/packed_sneaky-4.stderr [new file with mode: 0644]
tests/ui/pin_project/private_in_public-enum.rs [new file with mode: 0644]
tests/ui/pin_project/private_in_public-enum.stderr [new file with mode: 0644]
tests/ui/pin_project/project_replace_unsized.rs [new file with mode: 0644]
tests/ui/pin_project/project_replace_unsized.stderr [new file with mode: 0644]
tests/ui/pin_project/project_replace_unsized_fn_params.rs [new file with mode: 0644]
tests/ui/pin_project/project_replace_unsized_fn_params.stderr [new file with mode: 0644]
tests/ui/pin_project/remove-attr-from-field.rs [new file with mode: 0644]
tests/ui/pin_project/remove-attr-from-field.stderr [new file with mode: 0644]
tests/ui/pin_project/remove-attr-from-struct.rs [new file with mode: 0644]
tests/ui/pin_project/remove-attr-from-struct.stderr [new file with mode: 0644]
tests/ui/pin_project/safe_packed_borrows.rs [new file with mode: 0644]
tests/ui/pin_project/safe_packed_borrows.stderr [new file with mode: 0644]
tests/ui/pin_project/unaligned_references.rs [new file with mode: 0644]
tests/ui/pin_project/unaligned_references.stderr [new file with mode: 0644]
tests/ui/pin_project/unpin_sneaky.rs [new file with mode: 0644]
tests/ui/pin_project/unpin_sneaky.stderr [new file with mode: 0644]
tests/ui/pin_project/visibility.rs [new file with mode: 0644]
tests/ui/pin_project/visibility.stderr [new file with mode: 0644]
tests/ui/pinned_drop/call-drop-inner.rs [new file with mode: 0644]
tests/ui/pinned_drop/call-drop-inner.stderr [new file with mode: 0644]
tests/ui/pinned_drop/conditional-drop-impl.rs [new file with mode: 0644]
tests/ui/pinned_drop/conditional-drop-impl.stderr [new file with mode: 0644]
tests/ui/pinned_drop/forget-pinned-drop-impl.rs [new file with mode: 0644]
tests/ui/pinned_drop/forget-pinned-drop-impl.stderr [new file with mode: 0644]
tests/ui/pinned_drop/invalid-self.rs [new file with mode: 0644]
tests/ui/pinned_drop/invalid-self.stderr [new file with mode: 0644]
tests/ui/pinned_drop/invalid.rs [new file with mode: 0644]
tests/ui/pinned_drop/invalid.stderr [new file with mode: 0644]
tests/ui/pinned_drop/pinned-drop-no-attr-arg.rs [new file with mode: 0644]
tests/ui/pinned_drop/pinned-drop-no-attr-arg.stderr [new file with mode: 0644]
tests/ui/pinned_drop/self.rs [new file with mode: 0644]
tests/ui/pinned_drop/self.stderr [new file with mode: 0644]
tests/ui/pinned_drop/unsafe-call.rs [new file with mode: 0644]
tests/ui/pinned_drop/unsafe-call.stderr [new file with mode: 0644]
tests/ui/unsafe_unpin/conflict-unpin.rs [new file with mode: 0644]
tests/ui/unsafe_unpin/conflict-unpin.stderr [new file with mode: 0644]
tests/ui/unstable-features/README.md [new file with mode: 0644]
tests/ui/unstable-features/marker_trait_attr-feature-gate.rs [new file with mode: 0644]
tests/ui/unstable-features/marker_trait_attr-feature-gate.stderr [new file with mode: 0644]
tests/ui/unstable-features/marker_trait_attr.rs [new file with mode: 0644]
tests/ui/unstable-features/marker_trait_attr.stderr [new file with mode: 0644]
tests/ui/unstable-features/negative_impls.rs [new file with mode: 0644]
tests/ui/unstable-features/negative_impls.stderr [new file with mode: 0644]
tests/ui/unstable-features/overlapping_marker_traits-feature-gate.rs [new file with mode: 0644]
tests/ui/unstable-features/overlapping_marker_traits-feature-gate.stderr [new file with mode: 0644]
tests/ui/unstable-features/overlapping_marker_traits.rs [new file with mode: 0644]
tests/ui/unstable-features/overlapping_marker_traits.stderr [new file with mode: 0644]
tests/ui/unstable-features/trivial_bounds-feature-gate.rs [new file with mode: 0644]
tests/ui/unstable-features/trivial_bounds-feature-gate.stderr [new file with mode: 0644]
tests/ui/unstable-features/trivial_bounds.rs [new file with mode: 0644]
tests/ui/unstable-features/trivial_bounds.stderr [new file with mode: 0644]
tests/unsafe_unpin.rs [new file with mode: 0644]

diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644 (file)
index 0000000..401be20
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "git": {
+    "sha1": "d1c11dc50f88330cfb05ac55aaa06c28877eb1d6"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644 (file)
index 0000000..76e245f
--- /dev/null
@@ -0,0 +1,758 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+This project adheres to [Semantic Versioning](https://semver.org).
+
+<!--
+Note: In this file, do not use the hard wrap in the middle of a sentence for compatibility with GitHub comment style markdown rendering.
+-->
+
+## [Unreleased]
+
+## [1.0.12] - 2022-08-15
+
+- Suppress `unused_tuple_struct_fields` lint in generated code.
+
+## [1.0.11] - 2022-07-02
+
+- [Suppress `dead_code` lint in generated code.](https://github.com/taiki-e/pin-project/pull/346)
+
+## [1.0.10] - 2021-12-31
+
+- Revert the increase of the minimal version of `syn` that was done in 1.0.9.
+
+## [1.0.9] - 2021-12-26
+
+- [Prevent abuse of private module.](https://github.com/taiki-e/pin-project/pull/336)
+
+- Update minimal version of `syn` to 1.0.84.
+
+## [1.0.8] - 2021-07-21
+
+- [Suppress `clippy::use_self` and `clippy::type_repetition_in_bounds` lints in generated code.](https://github.com/taiki-e/pin-project/pull/331)
+
+## [1.0.7] - 2021-04-16
+
+- [Fix compile error when using `self::` as prefix of path inside `#[pinned_drop]` impl.](https://github.com/taiki-e/pin-project/pull/326)
+
+## [1.0.6] - 2021-03-25
+
+- [Suppress `clippy::semicolon_if_nothing_returned` lint in generated code.](https://github.com/taiki-e/pin-project/pull/318)
+
+## [1.0.5] - 2021-02-03
+
+- [Suppress `deprecated` lint in generated code.](https://github.com/taiki-e/pin-project/pull/313)
+
+## [1.0.4] - 2021-01-09
+
+- [Suppress `clippy::ref_option_ref` lint in generated code.](https://github.com/taiki-e/pin-project/pull/308)
+
+## [1.0.3] - 2021-01-05
+
+- Exclude unneeded files from crates.io.
+
+## [1.0.2] - 2020-11-18
+
+- [Suppress `clippy::unknown_clippy_lints` lint in generated code.](https://github.com/taiki-e/pin-project/pull/303)
+
+## [1.0.1] - 2020-10-15
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/commit/ddcd88079ba2d82857c365f2a3543ad146ade54c).
+
+- [Fix warnings when `#[pin_project]` attribute used within `macro_rules!` macros.](https://github.com/taiki-e/pin-project/pull/298)
+
+## [1.0.0] - 2020-10-13
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/commit/ddcd88079ba2d82857c365f2a3543ad146ade54c).
+
+- [Remove deprecated `#[project]`, `#[project_ref]`, and `#[project_replace]` attributes.](https://github.com/taiki-e/pin-project/pull/265)
+
+  Name the projected type by passing an argument with the same name as the method to the `#[pin_project]` attribute instead:
+
+  ```diff
+  - #[pin_project]
+  + #[pin_project(project = EnumProj)]
+    enum Enum<T> {
+        Variant(#[pin] T),
+    }
+
+  - #[project]
+    fn func<T>(x: Pin<&mut Enum<T>>) {
+  -     #[project]
+        match x.project() {
+  -         Enum::Variant(_) => { /* ... */ }
+  +         EnumProj::Variant(_) => { /* ... */ }
+        }
+    }
+  ```
+
+- [Remove deprecated `Replace` argument from `#[pin_project]` attribute.](https://github.com/taiki-e/pin-project/pull/266) Use `project_replace` argument instead.
+
+- [Optimize code generation when used on enums.](https://github.com/taiki-e/pin-project/pull/270)
+
+- [Raise the minimum supported Rust version of this crate from Rust 1.34 to Rust 1.37.](https://github.com/taiki-e/pin-project/pull/292)
+
+- Suppress `explicit_outlives_requirements`, `box_pointers`, `clippy::large_enum_variant`, `clippy::pattern_type_mismatch`, `clippy::implicit_return`, and `clippy::redundant_pub_crate` lints in generated code. ([#276](https://github.com/taiki-e/pin-project/pull/276), [#277](https://github.com/taiki-e/pin-project/pull/277), [#284](https://github.com/taiki-e/pin-project/pull/284))
+
+- Diagnostic improvements.
+
+Changes since the 1.0.0-alpha.1 release:
+
+- [Fix drop order of pinned fields in `project_replace`.](https://github.com/taiki-e/pin-project/pull/287)
+
+- Update minimal version of `syn` to 1.0.44.
+
+## [1.0.0-alpha.1] - 2020-09-22
+
+- [Remove deprecated `#[project]`, `#[project_ref]`, and `#[project_replace]` attributes.](https://github.com/taiki-e/pin-project/pull/265)
+
+  Name the projected type by passing an argument with the same name as the method to the `#[pin_project]` attribute instead:
+
+  ```diff
+  - #[pin_project]
+  + #[pin_project(project = EnumProj)]
+    enum Enum<T> {
+        Variant(#[pin] T),
+    }
+
+  - #[project]
+    fn func<T>(x: Pin<&mut Enum<T>>) {
+  -     #[project]
+        match x.project() {
+  -         Enum::Variant(_) => { /* ... */ }
+  +         EnumProj::Variant(_) => { /* ... */ }
+        }
+    }
+  ```
+
+- [Remove deprecated `Replace` argument from `#[pin_project]` attribute.](https://github.com/taiki-e/pin-project/pull/266) Use `project_replace` argument instead.
+
+- [Optimize code generation when used on enums.](https://github.com/taiki-e/pin-project/pull/270)
+
+- Suppress `explicit_outlives_requirements`, `box_pointers`, `clippy::large_enum_variant`, `clippy::pattern_type_mismatch`, and `clippy::implicit_return` lints in generated code. ([#276](https://github.com/taiki-e/pin-project/pull/276), [#277](https://github.com/taiki-e/pin-project/pull/277))
+
+- Diagnostic improvements.
+
+See also [tracking issue for 1.0 release](https://github.com/taiki-e/pin-project/issues/264).
+
+## [0.4.30] - 2022-07-02
+
+- [Suppress `dead_code` lint in generated code.](https://github.com/taiki-e/pin-project/pull/347)
+
+## [0.4.29] - 2021-12-26
+
+- [Fix compile error with `syn` 1.0.84 and later.](https://github.com/taiki-e/pin-project/pull/335)
+
+## [0.4.28] - 2021-03-28
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Fix `unused_must_use` warning on unused borrows, which will be added to rustc in the future.](https://github.com/taiki-e/pin-project/pull/322) See [#322](https://github.com/taiki-e/pin-project/pull/322) for more details.
+
+  (Note: 1.0 does not have this problem.)
+
+## [0.4.27] - 2020-10-11
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- Update minimal version of `syn` to 1.0.44.
+
+## [0.4.26] - 2020-10-04
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Fix drop order of pinned fields in `project_replace`.](https://github.com/taiki-e/pin-project/pull/287)
+
+## [0.4.25] - 2020-10-01
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Suppress `drop_bounds` lint, which will be added to rustc in the future.](https://github.com/taiki-e/pin-project/pull/273) See [#272](https://github.com/taiki-e/pin-project/issues/272) for more details.
+
+  (Note: 1.0.0-alpha.1 already contains this change.)
+
+## [0.4.24] - 2020-09-26
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Fix compatibility of generated code with `forbid(future_incompatible)`.](https://github.com/taiki-e/pin-project/pull/282)
+
+  Note: This does not guarantee compatibility with `forbid(future_incompatible)` in the future.
+  If rustc adds a new lint, we may not be able to keep this.
+
+## [0.4.23] - 2020-07-27
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Fix compile error with `?Sized` type parameters.](https://github.com/taiki-e/pin-project/pull/263)
+
+## [0.4.22] - 2020-06-14
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- Documentation improvements.
+
+## [0.4.21] - 2020-06-13
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Deprecated `#[project]`, `#[project_ref]`, and `#[project_replace]` attributes due to some unfixable limitations.](https://github.com/taiki-e/pin-project/pull/244)
+
+  Consider naming the projected type by passing an argument with the same name as the method to the `#[pin_project]` attribute instead.
+
+  ```rust
+  #[pin_project(project = EnumProj)]
+  enum Enum<T> {
+      Variant(#[pin] T),
+  }
+
+  fn func<T>(x: Pin<&mut Enum<T>>) {
+      match x.project() {
+          EnumProj::Variant(y) => {
+              let _: Pin<&mut T> = y;
+          }
+      }
+  }
+  ```
+
+  See [#225](https://github.com/taiki-e/pin-project/pull/225) for more details.
+
+- [Support `Self` in fields and generics in type definitions.](https://github.com/taiki-e/pin-project/pull/245)
+
+- [Fix errors involving *"`self` value is a keyword only available in methods with `self` parameter"* in apparently correct code.](https://github.com/taiki-e/pin-project/pull/250)
+
+- Diagnostic improvements.
+
+## [0.4.20] - 2020-06-07
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [You can now use `project_replace` argument without Replace argument.](https://github.com/taiki-e/pin-project/pull/243)
+  This used to require you to specify both.
+
+  ```diff
+  - #[pin_project(Replace, project_replace = EnumProjOwn)]
+  + #[pin_project(project_replace = EnumProjOwn)]
+    enum Enum<T> {
+        Variant(#[pin] T)
+    }
+  ```
+
+- [Make `project_replace` argument an alias for `Replace` argument so that it can be used without a value.](https://github.com/taiki-e/pin-project/pull/243)
+
+  ```rust
+  #[pin_project(project_replace)]
+  enum Enum<T> {
+      Variant(#[pin] T)
+  }
+  ```
+
+  *The `Replace` argument will be deprecated in the future.*
+
+- [Suppress `unreachable_pub` lint in generated code.](https://github.com/taiki-e/pin-project/pull/240)
+
+## [0.4.19] - 2020-06-04
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Suppress `unused_results` lint in generated code.](https://github.com/taiki-e/pin-project/pull/239)
+
+## [0.4.18] - 2020-06-04
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Support `Self` in more syntax positions inside `#[pinned_drop]` impl.](https://github.com/taiki-e/pin-project/pull/230)
+
+- [Suppress `clippy::type_repetition_in_bounds` and `clippy::used_underscore_binding` lints in generated code.](https://github.com/taiki-e/pin-project/pull/233)
+
+- Documentation improvements.
+
+- Diagnostic improvements.
+
+## [0.4.17] - 2020-05-18
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Support naming the projection types.](https://github.com/taiki-e/pin-project/pull/202)
+
+  By passing an argument with the same name as the method to the attribute, you can name the projection type returned from the method:
+
+  ```rust
+  #[pin_project(project = EnumProj)]
+  enum Enum<T> {
+      Variant(#[pin] T),
+  }
+
+  fn func<T>(x: Pin<&mut Enum<T>>) {
+      match x.project() {
+          EnumProj::Variant(y) => {
+              let _: Pin<&mut T> = y;
+          }
+      }
+  }
+  ```
+
+## [0.4.16] - 2020-05-11
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Fix an issue that users can call internal function generated by `#[pinned_drop]`.](https://github.com/taiki-e/pin-project/pull/223)
+
+## [0.4.15] - 2020-05-10
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [`#[project]` attribute can now handle all `project*` attributes in that scope with one wrapper attribute.](https://github.com/taiki-e/pin-project/pull/220)
+
+## [0.4.14] - 2020-05-09
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Add `!Unpin` option to `#[pin_project]` attribute for guarantee the type is `!Unpin`.](https://github.com/taiki-e/pin-project/pull/219)
+
+  ```rust
+  #[pin_project(!Unpin)]
+  struct Struct<T, U> {
+      field: T,
+  }
+  ```
+
+  This is equivalent to use `#[pin]` attribute for `PhantomPinned` field.
+
+  ```rust
+  #[pin_project]
+  struct Struct<T, U> {
+      field: T,
+      #[pin] // Note that using `PhantomPinned` without `#[pin]` attribute has no effect.
+      _pin: PhantomPinned,
+  }
+  ```
+
+  *[Note: This raises the minimum supported Rust version of this crate from Rust 1.33 to Rust 1.34.](https://github.com/taiki-e/pin-project/pull/219#pullrequestreview-408644187)*
+
+- [Fix an issue where duplicate `#[project]` attributes were ignored.](https://github.com/taiki-e/pin-project/pull/218)
+
+- [Suppress `single_use_lifetimes` lint in generated code.](https://github.com/taiki-e/pin-project/pull/217)
+
+- [Support overlapping lifetime names in HRTB.](https://github.com/taiki-e/pin-project/pull/217)
+
+- [Hide generated items from --document-private-items.](https://github.com/taiki-e/pin-project/pull/211) See [#211](https://github.com/taiki-e/pin-project/pull/211) for details.
+
+- Documentation improvements.
+
+## [0.4.13] - 2020-05-07
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Fix a regression in 0.4.11.](https://github.com/taiki-e/pin-project/pull/207)
+
+  Changes from [0.4.10](https://github.com/taiki-e/pin-project/releases/tag/v0.4.10) and [0.4.12](https://github.com/taiki-e/pin-project/releases/tag/v0.4.12):
+
+  - [Fix an issue that `#[project]` on non-statement expression does not work without unstable features.](https://github.com/taiki-e/pin-project/pull/197)
+
+  - [Support overwriting the name of core crate.](https://github.com/taiki-e/pin-project/pull/199)
+
+  - [Suppress `clippy::needless_pass_by_value` lint in generated code of `#[pinned_drop]`.](https://github.com/taiki-e/pin-project/pull/200)
+
+  - Documentation improvements.
+
+  - Diagnostic improvements.
+
+## [0.4.12] - 2020-05-07
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- A release to avoid [a regression in 0.4.11](https://github.com/taiki-e/pin-project/issues/206). No code changes from [0.4.10](https://github.com/taiki-e/pin-project/releases/tag/v0.4.10).
+
+## [0.4.11] - 2020-05-07
+
+**Note:** This release has been yanked. See [#206](https://github.com/taiki-e/pin-project/issues/206) for details.
+
+- [Fix an issue that `#[project]` on non-statement expression does not work without unstable features.](https://github.com/taiki-e/pin-project/pull/197)
+
+- [Support overwriting the name of core crate.](https://github.com/taiki-e/pin-project/pull/199)
+
+- [Suppress `clippy::needless_pass_by_value` lint in generated code of `#[pinned_drop]`.](https://github.com/taiki-e/pin-project/pull/200)
+
+- Documentation improvements.
+
+- Diagnostic improvements.
+
+## [0.4.10] - 2020-05-04
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Add `project_replace` method and `#[project_replace]` attribute.](https://github.com/taiki-e/pin-project/pull/194)
+  `project_replace` method is optional and can be enabled by passing the `Replace` argument to `#[pin_project]` attribute.
+  See [the documentation](https://docs.rs/pin-project/0.4/pin_project/attr.pin_project.html#project_replace) for more details.
+
+- [Support `Self` and `self` in more syntax positions inside `#[pinned_drop]` impl.](https://github.com/taiki-e/pin-project/pull/190)
+
+- [Hide all generated items except for projected types from calling code.](https://github.com/taiki-e/pin-project/pull/192) See [#192](https://github.com/taiki-e/pin-project/pull/192) for details.
+
+## [0.4.9] - 2020-04-14
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Fix lifetime inference error when associated types are used in fields.](https://github.com/taiki-e/pin-project/pull/188)
+
+- [Fix compile error with tuple structs with `where` clauses.](https://github.com/taiki-e/pin-project/pull/186)
+
+- [`#[project]` attribute can now be used for `if let` expressions.](https://github.com/taiki-e/pin-project/pull/181)
+
+## [0.4.8] - 2020-01-27
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Ensure that users cannot implement `PinnedDrop` without proper attribute argument.](https://github.com/taiki-e/pin-project/pull/180)
+
+- [Fix use of `Self` in expression position inside `#[pinned_drop]` impl.](https://github.com/taiki-e/pin-project/pull/177)
+
+## [0.4.7] - 2020-01-20
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Fix support for lifetime bounds.](https://github.com/taiki-e/pin-project/pull/176)
+
+## [0.4.6] - 2019-11-20
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Fix compile error when there is `Self` in the where clause.](https://github.com/taiki-e/pin-project/pull/169)
+
+## [0.4.5] - 2019-10-21
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Fix compile error with `dyn` types.](https://github.com/taiki-e/pin-project/pull/158)
+
+## [0.4.4] - 2019-10-17
+
+**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335).
+
+- [Fix an issue where `PinnedDrop` implementations can call unsafe code without an unsafe block.](https://github.com/taiki-e/pin-project/pull/149)
+
+## [0.4.3] - 2019-10-15
+
+**Note:** This release has been yanked. See [#148](https://github.com/taiki-e/pin-project/pull/148) for details.
+
+- [`#[pin_project]` can now interoperate with `#[cfg_attr()]`.](https://github.com/taiki-e/pin-project/pull/135)
+
+- [`#[pin_project]` can now interoperate with `#[cfg()]` on tuple structs and tuple variants.](https://github.com/taiki-e/pin-project/pull/135)
+
+- [Fix support for DSTs(Dynamically Sized Types) on `#[pin_project(UnsafeUnpin)]`](https://github.com/taiki-e/pin-project/pull/120)
+
+- Diagnostic improvements.
+
+## [0.4.2] - 2019-09-29
+
+**Note:** This release has been yanked. See [#148](https://github.com/taiki-e/pin-project/pull/148) for details.
+
+- [Fix support for DSTs(Dynamically Sized Types).](https://github.com/taiki-e/pin-project/pull/113)
+
+## [0.4.1] - 2019-09-26
+
+**Note:** This release has been yanked. See [#148](https://github.com/taiki-e/pin-project/pull/148) for details.
+
+- [Fix an issue that caused an error when using `#[pin_project]` on a type that has `#[pin]` + `!Unpin` field with no generics or lifetime.](https://github.com/taiki-e/pin-project/pull/111)
+
+## [0.4.0] - 2019-09-25
+
+**Note:** This release has been yanked. See [#148](https://github.com/taiki-e/pin-project/pull/148) for details.
+
+- [**Pin projection has become a safe operation.**](https://github.com/taiki-e/pin-project/pull/18) In the absence of other unsafe code that you write, it is impossible to cause undefined behavior.
+
+- `#[unsafe_project]` attribute has been replaced with `#[pin_project]` attribute. ([#18](https://github.com/taiki-e/pin-project/pull/18), [#33](https://github.com/taiki-e/pin-project/pull/33))
+
+- [The `Unpin` argument has been removed - an `Unpin` impl is now generated by default.](https://github.com/taiki-e/pin-project/pull/18)
+
+- Drop impls must be specified with `#[pinned_drop]` instead of via a normal `Drop` impl. ([#18](https://github.com/taiki-e/pin-project/pull/18), [#33](https://github.com/taiki-e/pin-project/pull/33), [#86](https://github.com/taiki-e/pin-project/pull/86))
+
+- [`Unpin` impls must be specified with an impl of `UnsafeUnpin`, instead of implementing the normal `Unpin` trait.](https://github.com/taiki-e/pin-project/pull/18)
+
+- [`#[pin_project]` attribute now determines the visibility of the projection type/method is based on the original type.](https://github.com/taiki-e/pin-project/pull/96)
+
+- [`#[pin_project]` can now be used for public type with private field types.](https://github.com/taiki-e/pin-project/pull/53)
+
+- [`#[pin_project]` can now interoperate with `#[cfg()]`.](https://github.com/taiki-e/pin-project/pull/77)
+
+- [Add `project_ref` method to `#[pin_project]` types.](https://github.com/taiki-e/pin-project/pull/93)
+
+- [Add `#[project_ref]` attribute.](https://github.com/taiki-e/pin-project/pull/93)
+
+- [Remove "project_attr" feature and always enable `#[project]` attribute.](https://github.com/taiki-e/pin-project/pull/94)
+
+- [`#[project]` attribute can now be used for `impl` blocks.](https://github.com/taiki-e/pin-project/pull/46)
+
+- [`#[project]` attribute can now be used for `use` statements.](https://github.com/taiki-e/pin-project/pull/85)
+
+- [`#[project]` attribute now supports `match` expressions at the position of the initializer expression of `let` expressions.](https://github.com/taiki-e/pin-project/pull/51)
+
+Changes since the 0.4.0-beta.1 release:
+
+- [Fix an issue that caused an error when using `#[pin_project(UnsafeUnpin)]` and not providing a manual `UnsafeUnpin` implementation on a type with no generics or lifetime.](https://github.com/taiki-e/pin-project/pull/107)
+
+## [0.4.0-beta.1] - 2019-09-21
+
+- [Change the argument type of project method back to `self: Pin<&mut Self>`.](https://github.com/taiki-e/pin-project/pull/90)
+
+- [Remove "project_attr" feature and always enable `#[project]` attribute.](https://github.com/taiki-e/pin-project/pull/94)
+
+- [Remove "renamed" feature.](https://github.com/taiki-e/pin-project/pull/100)
+
+- [`#[project]` attribute can now be used for `use` statements.](https://github.com/taiki-e/pin-project/pull/85)
+
+- [Add `project_ref` method and `#[project_ref]` attribute.](https://github.com/taiki-e/pin-project/pull/93)
+
+- [`#[pin_project]` attribute now determines the visibility of the projection type/method is based on the original type.](https://github.com/taiki-e/pin-project/pull/96)
+
+## [0.4.0-alpha.11] - 2019-09-11
+
+- [Change #[pinned_drop] to trait implementation.](https://github.com/taiki-e/pin-project/pull/86)
+
+  ```rust
+  #[pinned_drop]
+  impl<T> PinnedDrop for Foo<'_, T> {
+      fn drop(mut self: Pin<&mut Self>) {
+          **self.project().was_dropped = true;
+      }
+  }
+  ```
+
+- Add some examples and generated code.
+
+- Diagnostic improvements.
+
+## [0.4.0-alpha.10] - 2019-09-07
+
+- [`#[pin_project]` can now interoperate with `#[cfg()]`.](https://github.com/taiki-e/pin-project/pull/77)
+
+- Documentation improvements.
+
+## [0.4.0-alpha.9] - 2019-09-05
+
+- [Add `project_into` method to `#[pin_project]` types](https://github.com/taiki-e/pin-project/pull/69). This can be useful when returning a pin projection from a method.
+
+  ```rust
+  fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
+      self.project_into().pinned
+  }
+  ```
+
+- [Prevent `UnpinStruct` from appearing in the document by default.](https://github.com/taiki-e/pin-project/pull/71) See [#71](https://github.com/taiki-e/pin-project/pull/71) for more details.
+
+## [0.4.0-alpha.8] - 2019-09-03
+
+- [Improve document of generated code.](https://github.com/taiki-e/pin-project/pull/62). Also added an option to control the document of generated code. See [#62](https://github.com/taiki-e/pin-project/pull/62) for more details.
+
+- [Diagnostic improvements.](https://github.com/taiki-e/pin-project/pull/61)
+
+## [0.4.0-alpha.7] - 2019-09-02
+
+- [Suppress `dead_code` lint in generated types.](https://github.com/taiki-e/pin-project/pull/57)
+
+## [0.4.0-alpha.6] - 2019-09-01
+
+- [Allow using `#[pin_project]` type with private field types](https://github.com/taiki-e/pin-project/pull/53)
+
+## [0.4.0-alpha.5] - 2019-08-24
+
+- [`#[project]` attribute now supports `match` expressions at the position of the initializer expression of `let` expressions.](https://github.com/taiki-e/pin-project/pull/51)
+
+## [0.4.0-alpha.4] - 2019-08-23
+
+- Suppress `clippy::drop_bounds` lint in generated code.
+
+## [0.4.0-alpha.3] - 2019-08-23
+
+- [Change `project` method generated by `#[pin_project]` attribute to take an `&mut Pin<&mut Self>` argument.](https://github.com/taiki-e/pin-project/pull/47)
+
+- [`#[project]` attribute can now be used for impl blocks.](https://github.com/taiki-e/pin-project/pull/46)
+
+- [`#[pin_project]` attribute can now detect that the type used does not have its own drop implementation without actually implementing drop.](https://github.com/taiki-e/pin-project/pull/48) This removed some restrictions.
+
+## [0.4.0-alpha.2] - 2019-08-13
+
+- Update `proc-macro2`, `syn`, and `quote` to 1.0.
+
+## [0.4.0-alpha.1] - 2019-08-11
+
+- **Pin projection has become a safe operation.**
+
+- `#[unsafe_project]` has been replaced with `#[pin_project]`.
+
+- The `Unpin` argument has been removed - an `Unpin` impl is now generated by default.
+
+- Drop impls must be specified with `#[pinned_drop]` instead of via a normal `Drop` impl.
+
+- `Unpin` impls must be specified with an impl of `UnsafeUnpin`, instead of implementing the normal `Unpin` trait.
+
+- Make `#[project]` attribute disabled by default.
+
+See also [tracking issue for 0.4 release](https://github.com/taiki-e/pin-project/issues/21).
+
+## [0.3.5] - 2019-08-14
+
+- Update `proc-macro2`, `syn`, and `quote` to 1.0.
+
+## [0.3.4] - 2019-07-21
+
+- Diagnostic improvements.
+
+## [0.3.3] - 2019-07-15
+
+**Note:** This release has been yanked. See [#16](https://github.com/taiki-e/pin-project/issues/16) for details.
+
+- Diagnostic improvements.
+
+## [0.3.2] - 2019-03-30
+
+- Avoid suffixes on tuple index.
+
+## [0.3.1] - 2019-03-02
+
+- Documentation improvements.
+
+- Update minimum `syn` version to 0.15.22.
+
+## [0.3.0] - 2019-02-20
+
+- Remove `unsafe_fields` attribute.
+
+- Remove `unsafe_variants` attribute.
+
+## [0.2.2] - 2019-02-20
+
+- Fix a bug that generates incorrect code for the some structures with trait bounds on type generics.
+
+## [0.2.1] - 2019-02-20
+
+- Fix a bug that generates incorrect code for the structures with where clause and associated type fields.
+
+## [0.2.0] - 2019-02-11
+
+- Make `unsafe_fields` optional.
+
+- Documentation improvements.
+
+## [0.1.8] - 2019-02-02
+
+- Add the feature to create projected enums to `unsafe_project`.
+
+- Add `project` attribute to support pattern matching.
+
+## [0.1.7] - 2019-01-19
+
+- Fix documentation.
+
+## [0.1.6] - 2019-01-19
+
+- `unsafe_fields` can now opt-out.
+
+- Add `unsafe_variants` attribute. This attribute is available if pin-project is built with the "unsafe_variants" feature.
+
+## [0.1.5] - 2019-01-17
+
+- Add support for tuple struct to `unsafe_project`.
+
+## [0.1.4] - 2019-01-12
+
+- Add options for automatically implementing `Unpin` to both `unsafe_project` and `unsafe_fields`.
+
+## [0.1.3] - 2019-01-11
+
+- Fix dependencies.
+
+- Add `unsafe_fields` attribute.
+
+## [0.1.2] - 2019-01-09
+
+- Documentation improvements.
+
+## [0.1.1] - 2019-01-08
+
+- Rename from `unsafe_pin_project` to `unsafe_project`.
+
+## [0.1.0] - 2019-01-08
+
+**Note:** This release has been yanked.
+
+Initial release
+
+[Unreleased]: https://github.com/taiki-e/pin-project/compare/v1.0.12...HEAD
+[1.0.12]: https://github.com/taiki-e/pin-project/compare/v1.0.11...v1.0.12
+[1.0.11]: https://github.com/taiki-e/pin-project/compare/v1.0.10...v1.0.11
+[1.0.10]: https://github.com/taiki-e/pin-project/compare/v1.0.9...v1.0.10
+[1.0.9]: https://github.com/taiki-e/pin-project/compare/v1.0.8...v1.0.9
+[1.0.8]: https://github.com/taiki-e/pin-project/compare/v1.0.7...v1.0.8
+[1.0.7]: https://github.com/taiki-e/pin-project/compare/v1.0.6...v1.0.7
+[1.0.6]: https://github.com/taiki-e/pin-project/compare/v1.0.5...v1.0.6
+[1.0.5]: https://github.com/taiki-e/pin-project/compare/v1.0.4...v1.0.5
+[1.0.4]: https://github.com/taiki-e/pin-project/compare/v1.0.3...v1.0.4
+[1.0.3]: https://github.com/taiki-e/pin-project/compare/v1.0.2...v1.0.3
+[1.0.2]: https://github.com/taiki-e/pin-project/compare/v1.0.1...v1.0.2
+[1.0.1]: https://github.com/taiki-e/pin-project/compare/v1.0.0...v1.0.1
+[1.0.0]: https://github.com/taiki-e/pin-project/compare/v1.0.0-alpha.1...v1.0.0
+[1.0.0-alpha.1]: https://github.com/taiki-e/pin-project/compare/v0.4.23...v1.0.0-alpha.1
+[0.4.30]: https://github.com/taiki-e/pin-project/compare/v0.4.29...v0.4.30
+[0.4.29]: https://github.com/taiki-e/pin-project/compare/v0.4.28...v0.4.29
+[0.4.28]: https://github.com/taiki-e/pin-project/compare/v0.4.27...v0.4.28
+[0.4.27]: https://github.com/taiki-e/pin-project/compare/v0.4.26...v0.4.27
+[0.4.26]: https://github.com/taiki-e/pin-project/compare/v0.4.25...v0.4.26
+[0.4.25]: https://github.com/taiki-e/pin-project/compare/v0.4.24...v0.4.25
+[0.4.24]: https://github.com/taiki-e/pin-project/compare/v0.4.23...v0.4.24
+[0.4.23]: https://github.com/taiki-e/pin-project/compare/v0.4.22...v0.4.23
+[0.4.22]: https://github.com/taiki-e/pin-project/compare/v0.4.21...v0.4.22
+[0.4.21]: https://github.com/taiki-e/pin-project/compare/v0.4.20...v0.4.21
+[0.4.20]: https://github.com/taiki-e/pin-project/compare/v0.4.19...v0.4.20
+[0.4.19]: https://github.com/taiki-e/pin-project/compare/v0.4.18...v0.4.19
+[0.4.18]: https://github.com/taiki-e/pin-project/compare/v0.4.17...v0.4.18
+[0.4.17]: https://github.com/taiki-e/pin-project/compare/v0.4.16...v0.4.17
+[0.4.16]: https://github.com/taiki-e/pin-project/compare/v0.4.15...v0.4.16
+[0.4.15]: https://github.com/taiki-e/pin-project/compare/v0.4.14...v0.4.15
+[0.4.14]: https://github.com/taiki-e/pin-project/compare/v0.4.13...v0.4.14
+[0.4.13]: https://github.com/taiki-e/pin-project/compare/v0.4.11...v0.4.13
+[0.4.12]: https://github.com/taiki-e/pin-project/compare/v0.4.10...v0.4.12
+[0.4.11]: https://github.com/taiki-e/pin-project/compare/v0.4.10...v0.4.11
+[0.4.10]: https://github.com/taiki-e/pin-project/compare/v0.4.9...v0.4.10
+[0.4.9]: https://github.com/taiki-e/pin-project/compare/v0.4.8...v0.4.9
+[0.4.8]: https://github.com/taiki-e/pin-project/compare/v0.4.7...v0.4.8
+[0.4.7]: https://github.com/taiki-e/pin-project/compare/v0.4.6...v0.4.7
+[0.4.6]: https://github.com/taiki-e/pin-project/compare/v0.4.5...v0.4.6
+[0.4.5]: https://github.com/taiki-e/pin-project/compare/v0.4.4...v0.4.5
+[0.4.4]: https://github.com/taiki-e/pin-project/compare/v0.4.3...v0.4.4
+[0.4.3]: https://github.com/taiki-e/pin-project/compare/v0.4.2...v0.4.3
+[0.4.2]: https://github.com/taiki-e/pin-project/compare/v0.4.1...v0.4.2
+[0.4.1]: https://github.com/taiki-e/pin-project/compare/v0.4.0...v0.4.1
+[0.4.0]: https://github.com/taiki-e/pin-project/compare/v0.4.0-beta.1...v0.4.0
+[0.4.0-beta.1]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.11...v0.4.0-beta.1
+[0.4.0-alpha.11]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.10...v0.4.0-alpha.11
+[0.4.0-alpha.10]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.9...v0.4.0-alpha.10
+[0.4.0-alpha.9]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.8...v0.4.0-alpha.9
+[0.4.0-alpha.8]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.7...v0.4.0-alpha.8
+[0.4.0-alpha.7]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.6...v0.4.0-alpha.7
+[0.4.0-alpha.6]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.5...v0.4.0-alpha.6
+[0.4.0-alpha.5]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.4...v0.4.0-alpha.5
+[0.4.0-alpha.4]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.3...v0.4.0-alpha.4
+[0.4.0-alpha.3]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.2...v0.4.0-alpha.3
+[0.4.0-alpha.2]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.1...v0.4.0-alpha.2
+[0.4.0-alpha.1]: https://github.com/taiki-e/pin-project/compare/v0.3.5...v0.4.0-alpha.1
+[0.3.5]: https://github.com/taiki-e/pin-project/compare/v0.3.4...v0.3.5
+[0.3.4]: https://github.com/taiki-e/pin-project/compare/v0.3.3...v0.3.4
+[0.3.3]: https://github.com/taiki-e/pin-project/compare/v0.3.2...v0.3.3
+[0.3.2]: https://github.com/taiki-e/pin-project/compare/v0.3.1...v0.3.2
+[0.3.1]: https://github.com/taiki-e/pin-project/compare/v0.3.0...v0.3.1
+[0.3.0]: https://github.com/taiki-e/pin-project/compare/v0.2.2...v0.3.0
+[0.2.2]: https://github.com/taiki-e/pin-project/compare/v0.2.1...v0.2.2
+[0.2.1]: https://github.com/taiki-e/pin-project/compare/v0.2.0...v0.2.1
+[0.2.0]: https://github.com/taiki-e/pin-project/compare/v0.1.8...v0.2.0
+[0.1.8]: https://github.com/taiki-e/pin-project/compare/v0.1.7...v0.1.8
+[0.1.7]: https://github.com/taiki-e/pin-project/compare/v0.1.6...v0.1.7
+[0.1.6]: https://github.com/taiki-e/pin-project/compare/v0.1.5...v0.1.6
+[0.1.5]: https://github.com/taiki-e/pin-project/compare/v0.1.4...v0.1.5
+[0.1.4]: https://github.com/taiki-e/pin-project/compare/v0.1.3...v0.1.4
+[0.1.3]: https://github.com/taiki-e/pin-project/compare/v0.1.2...v0.1.3
+[0.1.2]: https://github.com/taiki-e/pin-project/compare/v0.1.1...v0.1.2
+[0.1.1]: https://github.com/taiki-e/pin-project/compare/v0.1.0...v0.1.1
+[0.1.0]: https://github.com/taiki-e/pin-project/releases/tag/v0.1.0
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644 (file)
index 0000000..502ac21
--- /dev/null
@@ -0,0 +1,222 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "diff"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
+
+[[package]]
+name = "glob"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+
+[[package]]
+name = "itoa"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
+
+[[package]]
+name = "macrotest"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7489ae0986ce45414b7b3122c2e316661343ecf396b206e3e15f07c846616f10"
+dependencies = [
+ "diff",
+ "glob",
+ "prettyplease",
+ "serde",
+ "serde_json",
+ "syn",
+ "toml",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
+
+[[package]]
+name = "pin-project"
+version = "1.0.12"
+dependencies = [
+ "macrotest",
+ "pin-project-internal",
+ "rustversion",
+ "static_assertions",
+ "trybuild",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "prettyplease"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "697ae720ee02011f439e0701db107ffe2916d83f718342d65d7f8bf7b8a5fee9"
+dependencies = [
+ "proc-macro2",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
+
+[[package]]
+name = "ryu"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
+
+[[package]]
+name = "serde"
+version = "1.0.143"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.143"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "syn"
+version = "1.0.99"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "toml"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "trybuild"
+version = "1.0.64"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7f408301c7480f9e6294eb779cfc907f54bd901a9660ef24d7f233ed5376485"
+dependencies = [
+ "glob",
+ "once_cell",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "termcolor",
+ "toml",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644 (file)
index 0000000..9ad85ba
--- /dev/null
@@ -0,0 +1,54 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+rust-version = "1.37"
+name = "pin-project"
+version = "1.0.12"
+exclude = [
+    "/.*",
+    "/ci",
+    "/tools",
+]
+description = """
+A crate for safe and ergonomic pin-projection.
+"""
+readme = "README.md"
+keywords = [
+    "pin",
+    "macros",
+    "attribute",
+]
+categories = [
+    "no-std",
+    "rust-patterns",
+]
+license = "Apache-2.0 OR MIT"
+repository = "https://github.com/taiki-e/pin-project"
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[dependencies.pin-project-internal]
+version = "=1.0.12"
+
+[dev-dependencies.macrotest]
+version = "1.0.9"
+
+[dev-dependencies.rustversion]
+version = "1"
+
+[dev-dependencies.static_assertions]
+version = "1"
+
+[dev-dependencies.trybuild]
+version = "1.0.49"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644 (file)
index 0000000..6ddfa42
--- /dev/null
@@ -0,0 +1,39 @@
+[package]
+name = "pin-project"
+version = "1.0.12"
+edition = "2018"
+rust-version = "1.37"
+license = "Apache-2.0 OR MIT"
+repository = "https://github.com/taiki-e/pin-project"
+keywords = ["pin", "macros", "attribute"]
+categories = ["no-std", "rust-patterns"]
+exclude = ["/.*", "/ci", "/tools"]
+description = """
+A crate for safe and ergonomic pin-projection.
+"""
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[workspace]
+members = [
+    "pin-project-internal",
+    "tests/auxiliary/macro",
+    "tests/doc",
+    "tests/no-core",
+    "tests/no-std",
+    "tests/rust-2015",
+]
+
+[dependencies]
+pin-project-internal = { version = "=1.0.12", path = "pin-project-internal" }
+
+[dev-dependencies]
+pin-project-auxiliary-macro = { path = "tests/auxiliary/macro" }
+macrotest = "1.0.9"
+rustversion = "1"
+static_assertions = "1"
+trybuild = "1.0.49"
+
+[patch.crates-io]
+prettyplease = { git = "https://github.com/taiki-e/prettyplease.git", branch = "dev" } # lower MSRV
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
new file mode 100644 (file)
index 0000000..f433b1a
--- /dev/null
@@ -0,0 +1,177 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
diff --git a/LICENSE-MIT b/LICENSE-MIT
new file mode 100644 (file)
index 0000000..31aa793
--- /dev/null
@@ -0,0 +1,23 @@
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..0a30654
--- /dev/null
+++ b/README.md
@@ -0,0 +1,99 @@
+# pin-project
+
+[![crates.io](https://img.shields.io/crates/v/pin-project?style=flat-square&logo=rust)](https://crates.io/crates/pin-project)
+[![docs.rs](https://img.shields.io/badge/docs.rs-pin--project-blue?style=flat-square&logo=docs.rs)](https://docs.rs/pin-project)
+[![license](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue?style=flat-square)](#license)
+[![rustc](https://img.shields.io/badge/rustc-1.37+-blue?style=flat-square&logo=rust)](https://www.rust-lang.org)
+[![build status](https://img.shields.io/github/workflow/status/taiki-e/pin-project/CI/main?style=flat-square&logo=github)](https://github.com/taiki-e/pin-project/actions)
+
+A crate for safe and ergonomic [pin-projection].
+
+## Usage
+
+Add this to your `Cargo.toml`:
+
+```toml
+[dependencies]
+pin-project = "1"
+```
+
+*Compiler support: requires rustc 1.37+*
+
+## Examples
+
+[`#[pin_project]`][`pin_project`] attribute creates projection types
+covering all the fields of struct or enum.
+
+```rust
+use pin_project::pin_project;
+use std::pin::Pin;
+
+#[pin_project]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+
+impl<T, U> Struct<T, U> {
+    fn method(self: Pin<&mut Self>) {
+        let this = self.project();
+        let _: Pin<&mut T> = this.pinned; // Pinned reference to the field
+        let _: &mut U = this.unpinned; // Normal reference to the field
+    }
+}
+```
+
+[*code like this will be generated*][struct-default-expanded]
+
+To use `#[pin_project]` on enums, you need to name the projection type
+returned from the method.
+
+```rust
+use pin_project::pin_project;
+use std::pin::Pin;
+
+#[pin_project(project = EnumProj)]
+enum Enum<T, U> {
+    Pinned(#[pin] T),
+    Unpinned(U),
+}
+
+impl<T, U> Enum<T, U> {
+    fn method(self: Pin<&mut Self>) {
+        match self.project() {
+            EnumProj::Pinned(x) => {
+                let _: Pin<&mut T> = x;
+            }
+            EnumProj::Unpinned(y) => {
+                let _: &mut U = y;
+            }
+        }
+    }
+}
+```
+
+[*code like this will be generated*][enum-default-expanded]
+
+See [documentation](https://docs.rs/pin-project) for more details, and
+see [examples] directory for more examples and generated code.
+
+## Related Projects
+
+- [pin-project-lite]: A lightweight version of pin-project written with declarative macros.
+
+[`pin_project`]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html
+[enum-default-expanded]: examples/enum-default-expanded.rs
+[examples]: examples/README.md
+[pin-project-lite]: https://github.com/taiki-e/pin-project-lite
+[pin-projection]: https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning
+[struct-default-expanded]: examples/struct-default-expanded.rs
+
+## License
+
+Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or
+[MIT license](LICENSE-MIT) at your option.
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall
+be dual licensed as above, without any additional terms or conditions.
diff --git a/examples/README.md b/examples/README.md
new file mode 100644 (file)
index 0000000..0f30a7f
--- /dev/null
@@ -0,0 +1,39 @@
+# 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/1/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/1/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/1/pin_project/attr.pin_project.html#project_replace-method)
+
+### Ensure `!Unpin` by `#[pin_project(!Unpin)]`
+
+- [example](not_unpin.rs)
+- [generated code](not_unpin-expanded.rs)
+- [`!Unpin` documentation](https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unpin)
+
+Note: These generated code examples are the little simplified version of the
+actual generated code. See [expansion tests](../tests#expansion-tests-expand-expandtestrs) if you
+want to see the exact version of the actual generated code.
diff --git a/examples/enum-default-expanded.rs b/examples/enum-default-expanded.rs
new file mode 100644 (file)
index 0000000..459ca39
--- /dev/null
@@ -0,0 +1,101 @@
+// Original code (./enum-default.rs):
+//
+// ```rust
+// #![allow(dead_code)]
+//
+// use pin_project::pin_project;
+//
+// #[pin_project(project = EnumProj)]
+// enum Enum<T, U> {
+//     Pinned(#[pin] T),
+//     Unpinned(U),
+// }
+//
+// fn main() {}
+// ```
+
+#![allow(dead_code, unused_imports, unused_parens, unknown_lints, renamed_and_removed_lints)]
+#![allow(
+    clippy::needless_lifetimes,
+    clippy::just_underscores_and_digits,
+    clippy::used_underscore_binding
+)]
+
+use pin_project::pin_project;
+
+// #[pin_project(project = EnumProj)]
+enum Enum<T, U> {
+    Pinned(/* #[pin] */ T),
+    Unpinned(U),
+}
+
+enum EnumProj<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Pinned(::pin_project::__private::Pin<&'pin mut (T)>),
+    Unpinned(&'pin mut (U)),
+}
+
+const _: () = {
+    // When `#[pin_project]` is used on enums, only named projection types and
+    // methods are generated because there is no way to access variants of
+    // projected types without naming it.
+    // (When `#[pin_project]` is used on structs, both methods are always generated.)
+
+    impl<T, U> Enum<T, U> {
+        fn project<'pin>(
+            self: ::pin_project::__private::Pin<&'pin mut Self>,
+        ) -> EnumProj<'pin, T, U> {
+            unsafe {
+                match self.get_unchecked_mut() {
+                    Self::Pinned(_0) => {
+                        EnumProj::Pinned(::pin_project::__private::Pin::new_unchecked(_0))
+                    }
+                    Self::Unpinned(_0) => EnumProj::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,
+            (::pin_project::__private::PhantomData<T>, ::pin_project::__private::PhantomData<U>),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> ::pin_project::__private::Unpin for Enum<T, U> where
+        __Enum<'pin, T, U>: ::pin_project::__private::Unpin
+    {
+    }
+    // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it.
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> ::pin_project::UnsafeUnpin for Enum<T, U> where
+        __Enum<'pin, T, U>: ::pin_project::__private::Unpin
+    {
+    }
+
+    // Ensure that enum does not implement `Drop`.
+    //
+    // See ./struct-default-expanded.rs for details.
+    trait EnumMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: ::pin_project::__private::Drop> EnumMustNotImplDrop for T {}
+    impl<T, U> EnumMustNotImplDrop for Enum<T, U> {}
+    // A dummy impl of `PinnedDrop`, to ensure that users don't accidentally
+    // write a non-functional `PinnedDrop` impls.
+    #[doc(hidden)]
+    impl<T, U> ::pin_project::__private::PinnedDrop for Enum<T, U> {
+        unsafe fn drop(self: ::pin_project::__private::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 (file)
index 0000000..bd3f2e6
--- /dev/null
@@ -0,0 +1,13 @@
+// See ./enum-default-expanded.rs for generated code.
+
+#![allow(dead_code)]
+
+use pin_project::pin_project;
+
+#[pin_project(project = EnumProj)]
+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 (file)
index 0000000..5700c12
--- /dev/null
@@ -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, unknown_lints, renamed_and_removed_lints)]
+#![allow(clippy::needless_lifetimes)]
+
+use pin_project::pin_project;
+
+// #[pin_project(!Unpin)]
+pub struct Struct<T, U> {
+    // #[pin]
+    pinned: T,
+    unpinned: U,
+}
+
+const _: () = {
+    pub(crate) struct __StructProjection<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    }
+    pub(crate) struct __StructProjectionRef<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin (T)>,
+        unpinned: &'pin (U),
+    }
+
+    impl<T, U> Struct<T, U> {
+        pub(crate) fn project<'pin>(
+            self: ::pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __StructProjection<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                __StructProjection {
+                    pinned: ::pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        pub(crate) fn project_ref<'pin>(
+            self: ::pin_project::__private::Pin<&'pin Self>,
+        ) -> __StructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_ref();
+                __StructProjectionRef {
+                    pinned: ::pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+    }
+
+    // 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.
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned;
+        let _ = &this.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::__private::Unpin for Struct<T, U> where
+        ::pin_project::__private::Wrapper<'pin, ::pin_project::__private::PhantomPinned>:
+            ::pin_project::__private::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 an `UnsafeUnpin`
+    // impl, they'll get a "conflicting implementations of trait" error when
+    // coherence checks are run.
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> ::pin_project::UnsafeUnpin for Struct<T, U> where
+        ::pin_project::__private::Wrapper<'pin, ::pin_project::__private::PhantomPinned>:
+            ::pin_project::__private::Unpin
+    {
+    }
+
+    // Ensure that struct does not implement `Drop`.
+    //
+    // See ./struct-default-expanded.rs for details.
+    trait StructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: ::pin_project::__private::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.
+    #[doc(hidden)]
+    impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
+        unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+
+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 (file)
index 0000000..2ad72a8
--- /dev/null
@@ -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 (file)
index 0000000..82207b6
--- /dev/null
@@ -0,0 +1,154 @@
+// Original code (./pinned_drop.rs):
+//
+// ```rust
+// #![allow(dead_code)]
+//
+// use std::pin::Pin;
+//
+// use pin_project::{pin_project, pinned_drop};
+//
+// #[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, unknown_lints, renamed_and_removed_lints)]
+#![allow(clippy::needless_lifetimes, clippy::mut_mut)]
+
+use std::pin::Pin;
+
+use pin_project::{pin_project, pinned_drop};
+
+// #[pin_project(PinnedDrop)]
+pub struct Struct<'a, T> {
+    was_dropped: &'a mut bool,
+    // #[pin]
+    field: T,
+}
+
+const _: () = {
+    pub(crate) struct __StructProjection<'pin, 'a, T>
+    where
+        Struct<'a, T>: 'pin,
+    {
+        was_dropped: &'pin mut (&'a mut bool),
+        field: ::pin_project::__private::Pin<&'pin mut (T)>,
+    }
+    pub(crate) struct __StructProjectionRef<'pin, 'a, T>
+    where
+        Struct<'a, T>: 'pin,
+    {
+        was_dropped: &'pin (&'a mut bool),
+        field: ::pin_project::__private::Pin<&'pin (T)>,
+    }
+
+    impl<'a, T> Struct<'a, T> {
+        pub(crate) fn project<'pin>(
+            self: ::pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __StructProjection<'pin, 'a, T> {
+            unsafe {
+                let Self { was_dropped, field } = self.get_unchecked_mut();
+                __StructProjection {
+                    was_dropped,
+                    field: ::pin_project::__private::Pin::new_unchecked(field),
+                }
+            }
+        }
+        pub(crate) fn project_ref<'pin>(
+            self: ::pin_project::__private::Pin<&'pin Self>,
+        ) -> __StructProjectionRef<'pin, 'a, T> {
+            unsafe {
+                let Self { was_dropped, field } = self.get_ref();
+                __StructProjectionRef {
+                    was_dropped,
+                    field: ::pin_project::__private::Pin::new_unchecked(field),
+                }
+            }
+        }
+    }
+
+    // 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.
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<'a, T>(this: &Struct<'a, T>) {
+        let _ = &this.was_dropped;
+        let _ = &this.field;
+    }
+
+    impl<'a, T> ::pin_project::__private::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::__private::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::__private::Unpin for Struct<'a, T> where
+        __Struct<'pin, 'a, T>: ::pin_project::__private::Unpin
+    {
+    }
+    // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it.
+    #[doc(hidden)]
+    unsafe impl<'pin, 'a, T> ::pin_project::UnsafeUnpin for Struct<'a, T> where
+        __Struct<'pin, 'a, T>: ::pin_project::__private::Unpin
+    {
+    }
+};
+
+// 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.**
+#[doc(hidden)]
+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 (file)
index 0000000..6fb8719
--- /dev/null
@@ -0,0 +1,23 @@
+// See ./pinned_drop-expanded.rs for generated code.
+
+#![allow(dead_code)]
+
+use std::pin::Pin;
+
+use pin_project::{pin_project, pinned_drop};
+
+#[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 (file)
index 0000000..445e570
--- /dev/null
@@ -0,0 +1,156 @@
+// Original code (./struct-default.rs):
+//
+// ```rust
+// #![allow(dead_code)]
+//
+// use pin_project::pin_project;
+//
+// #[pin_project(project_replace)]
+// struct Struct<T, U> {
+//     #[pin]
+//     pinned: T,
+//     unpinned: U,
+// }
+//
+// fn main() {}
+// ```
+
+#![allow(dead_code, unused_imports, unused_parens, unknown_lints, renamed_and_removed_lints)]
+#![allow(clippy::needless_lifetimes)]
+
+use pin_project::pin_project;
+
+// #[pin_project(project_replace)]
+struct Struct<T, U> {
+    // #[pin]
+    pinned: T,
+    unpinned: U,
+}
+
+const _: () = {
+    struct __StructProjection<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    }
+    struct __StructProjectionRef<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin (T)>,
+        unpinned: &'pin (U),
+    }
+    struct __StructProjectionOwned<T, U> {
+        pinned: ::pin_project::__private::PhantomData<T>,
+        unpinned: U,
+    }
+
+    impl<T, U> Struct<T, U> {
+        fn project<'pin>(
+            self: ::pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __StructProjection<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                __StructProjection {
+                    pinned: ::pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        fn project_ref<'pin>(
+            self: ::pin_project::__private::Pin<&'pin Self>,
+        ) -> __StructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_ref();
+                __StructProjectionRef {
+                    pinned: ::pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        fn project_replace(
+            self: ::pin_project::__private::Pin<&mut Self>,
+            __replacement: Self,
+        ) -> __StructProjectionOwned<T, U> {
+            unsafe {
+                let __self_ptr: *mut Self = self.get_unchecked_mut();
+
+                // 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::new(__self_ptr, __replacement);
+
+                let Self { pinned, unpinned } = &mut *__self_ptr;
+
+                // First, extract all the unpinned fields
+                let __result = __StructProjectionOwned {
+                    pinned: ::pin_project::__private::PhantomData,
+                    unpinned: ::pin_project::__private::ptr::read(unpinned),
+                };
+
+                // 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::new(pinned);
+                }
+
+                // Finally, return the result
+                __result
+            }
+        }
+    }
+
+    // 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.
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned;
+        let _ = &this.unpinned;
+    }
+
+    // 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,
+            (::pin_project::__private::PhantomData<T>, ::pin_project::__private::PhantomData<U>),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> ::pin_project::__private::Unpin for Struct<T, U> where
+        __Struct<'pin, T, U>: ::pin_project::__private::Unpin
+    {
+    }
+    // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it.
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> ::pin_project::UnsafeUnpin for Struct<T, U> where
+        __Struct<'pin, T, U>: ::pin_project::__private::Unpin
+    {
+    }
+
+    // Ensure that struct does not implement `Drop`.
+    //
+    // See ./struct-default-expanded.rs for details.
+    trait StructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: ::pin_project::__private::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.
+    #[doc(hidden)]
+    impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
+        unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+
+fn main() {}
diff --git a/examples/project_replace.rs b/examples/project_replace.rs
new file mode 100644 (file)
index 0000000..99cec18
--- /dev/null
@@ -0,0 +1,14 @@
+// See ./struct-default-expanded.rs for generated code.
+
+#![allow(dead_code)]
+
+use pin_project::pin_project;
+
+#[pin_project(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 (file)
index 0000000..d661099
--- /dev/null
@@ -0,0 +1,155 @@
+// 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, unknown_lints, renamed_and_removed_lints)]
+#![allow(clippy::needless_lifetimes)]
+
+use pin_project::pin_project;
+
+// #[pin_project]
+struct Struct<T, U> {
+    // #[pin]
+    pinned: T,
+    unpinned: U,
+}
+
+const _: () = {
+    struct __StructProjection<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    }
+    struct __StructProjectionRef<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin (T)>,
+        unpinned: &'pin (U),
+    }
+
+    impl<T, U> Struct<T, U> {
+        fn project<'pin>(
+            self: ::pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __StructProjection<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                __StructProjection {
+                    pinned: ::pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        fn project_ref<'pin>(
+            self: ::pin_project::__private::Pin<&'pin Self>,
+        ) -> __StructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_ref();
+                __StructProjectionRef {
+                    pinned: ::pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+    }
+
+    // Ensure that it's impossible to use pin projections on a #[repr(packed)]
+    // struct.
+    //
+    // Taking a reference to a packed field is UB, and applying
+    // `#[forbid(unaligned_references)]` makes sure that doing this 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.
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned;
+        let _ = &this.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,
+            (::pin_project::__private::PhantomData<T>, ::pin_project::__private::PhantomData<U>),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> ::pin_project::__private::Unpin for Struct<T, U> where
+        __Struct<'pin, T, U>: ::pin_project::__private::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 an `UnsafeUnpin`
+    // impl, they'll get a "conflicting implementations of trait" error when
+    // coherence checks are run.
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> ::pin_project::UnsafeUnpin for Struct<T, U> where
+        __Struct<'pin, T, U>: ::pin_project::__private::Unpin
+    {
+    }
+
+    // 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, drop_bounds)]
+    impl<T: ::pin_project::__private::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.
+    #[doc(hidden)]
+    impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
+        unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+
+fn main() {}
diff --git a/examples/struct-default.rs b/examples/struct-default.rs
new file mode 100644 (file)
index 0000000..46808a5
--- /dev/null
@@ -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 (file)
index 0000000..e9c7abc
--- /dev/null
@@ -0,0 +1,107 @@
+// 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, unknown_lints, renamed_and_removed_lints)]
+#![allow(clippy::needless_lifetimes)]
+
+use pin_project::{pin_project, UnsafeUnpin};
+
+// #[pin_project(UnsafeUnpin)]
+pub struct Struct<T, U> {
+    // #[pin]
+    pinned: T,
+    unpinned: U,
+}
+
+const _: () = {
+    pub(crate) struct __StructProjection<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    }
+    pub(crate) struct __StructProjectionRef<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin (T)>,
+        unpinned: &'pin (U),
+    }
+
+    impl<T, U> Struct<T, U> {
+        pub(crate) fn project<'pin>(
+            self: ::pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __StructProjection<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                __StructProjection {
+                    pinned: ::pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        pub(crate) fn project_ref<'pin>(
+            self: ::pin_project::__private::Pin<&'pin Self>,
+        ) -> __StructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_ref();
+                __StructProjectionRef {
+                    pinned: ::pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+    }
+
+    // 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.
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned;
+        let _ = &this.unpinned;
+    }
+
+    // Implement `Unpin` via `UnsafeUnpin`.
+    impl<'pin, T, U> ::pin_project::__private::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, drop_bounds)]
+    impl<T: ::pin_project::__private::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.
+    #[doc(hidden)]
+    impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
+        unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+
+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 (file)
index 0000000..5ec0cd2
--- /dev/null
@@ -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() {}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644 (file)
index 0000000..5fa9298
--- /dev/null
@@ -0,0 +1,315 @@
+//! A crate for safe and ergonomic [pin-projection].
+//!
+//! # Examples
+//!
+//! [`#[pin_project]`][`pin_project`] attribute creates projection types
+//! covering all the fields of struct or enum.
+//!
+//! ```rust
+//! use std::pin::Pin;
+//!
+//! use pin_project::pin_project;
+//!
+//! #[pin_project]
+//! struct Struct<T, U> {
+//!     #[pin]
+//!     pinned: T,
+//!     unpinned: U,
+//! }
+//!
+//! impl<T, U> Struct<T, U> {
+//!     fn method(self: Pin<&mut Self>) {
+//!         let this = self.project();
+//!         let _: Pin<&mut T> = this.pinned; // Pinned reference to the field
+//!         let _: &mut U = this.unpinned; // Normal reference to the field
+//!     }
+//! }
+//! ```
+//!
+//! [*code like this will be generated*][struct-default-expanded]
+//!
+//! To use `#[pin_project]` on enums, you need to name the projection type
+//! returned from the method.
+//!
+//! ```rust
+//! use std::pin::Pin;
+//!
+//! use pin_project::pin_project;
+//!
+//! #[pin_project(project = EnumProj)]
+//! enum Enum<T, U> {
+//!     Pinned(#[pin] T),
+//!     Unpinned(U),
+//! }
+//!
+//! impl<T, U> Enum<T, U> {
+//!     fn method(self: Pin<&mut Self>) {
+//!         match self.project() {
+//!             EnumProj::Pinned(x) => {
+//!                 let _: Pin<&mut T> = x;
+//!             }
+//!             EnumProj::Unpinned(y) => {
+//!                 let _: &mut U = y;
+//!             }
+//!         }
+//!     }
+//! }
+//! ```
+//!
+//! [*code like this will be generated*][enum-default-expanded]
+//!
+//! See [`#[pin_project]`][`pin_project`] attribute for more details, and
+//! see [examples] directory for more examples and generated code.
+//!
+//! [examples]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/README.md
+//! [enum-default-expanded]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/enum-default-expanded.rs
+//! [pin-projection]: core::pin#projections-and-structural-pinning
+//! [struct-default-expanded]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/struct-default-expanded.rs
+
+#![no_std]
+#![doc(test(
+    no_crate_inject,
+    attr(
+        deny(warnings, rust_2018_idioms, single_use_lifetimes),
+        allow(dead_code, unused_variables)
+    )
+))]
+#![warn(missing_docs, rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
+#![warn(
+    clippy::pedantic,
+    // lints for public library
+    clippy::alloc_instead_of_core,
+    clippy::exhaustive_enums,
+    clippy::exhaustive_structs,
+    clippy::std_instead_of_alloc,
+    clippy::std_instead_of_core,
+    // lints that help writing unsafe code
+    clippy::default_union_representation,
+    clippy::trailing_empty_array,
+    clippy::transmute_undefined_repr,
+    clippy::undocumented_unsafe_blocks,
+)]
+#![allow(clippy::needless_doctest_main)]
+
+#[doc(inline)]
+pub use pin_project_internal::pin_project;
+#[doc(inline)]
+pub use pin_project_internal::pinned_drop;
+
+/// A trait used for custom implementations of [`Unpin`].
+///
+/// This trait is used in conjunction with the `UnsafeUnpin` argument to
+/// the [`#[pin_project]`][macro@pin_project] attribute.
+///
+/// # Safety
+///
+/// The Rust [`Unpin`] trait is safe to implement - by itself,
+/// implementing it cannot lead to [undefined behavior][undefined-behavior].
+/// Undefined behavior can only occur when other unsafe code is used.
+///
+/// It turns out that using pin projections, which requires unsafe code,
+/// imposes additional requirements on an [`Unpin`] impl. Normally, all of this
+/// unsafety is contained within this crate, ensuring that it's impossible for
+/// you to violate any of the guarantees required by pin projection.
+///
+/// However, things change if you want to provide a custom [`Unpin`] impl
+/// for your `#[pin_project]` type. As stated in [the Rust
+/// documentation][pin-projection], you must be sure to only implement [`Unpin`]
+/// when all of your `#[pin]` fields (i.e. structurally pinned fields) are also
+/// [`Unpin`].
+///
+/// To help highlight this unsafety, the `UnsafeUnpin` trait is provided.
+/// Implementing this trait is logically equivalent to implementing [`Unpin`] -
+/// this crate will generate an [`Unpin`] impl for your type that 'forwards' to
+/// your `UnsafeUnpin` impl. However, this trait is `unsafe` - since your type
+/// uses structural pinning (otherwise, you wouldn't be using this crate!),
+/// you must be sure that your `UnsafeUnpin` impls follows all of
+/// the requirements for an [`Unpin`] impl of a structurally-pinned type.
+///
+/// Note that if you specify `#[pin_project(UnsafeUnpin)]`, but do *not*
+/// provide an impl of `UnsafeUnpin`, your type will never implement [`Unpin`].
+/// This is effectively the same thing as adding a [`PhantomPinned`] to your
+/// type.
+///
+/// Since this trait is `unsafe`, impls of it will be detected by the
+/// `unsafe_code` lint, and by tools like [`cargo geiger`][cargo-geiger].
+///
+/// # Examples
+///
+/// An `UnsafeUnpin` impl which, in addition to requiring that structurally
+/// pinned fields be [`Unpin`], imposes an additional requirement:
+///
+/// ```rust
+/// use pin_project::{pin_project, UnsafeUnpin};
+///
+/// #[pin_project(UnsafeUnpin)]
+/// struct Struct<K, V> {
+///     #[pin]
+///     field_1: K,
+///     field_2: V,
+/// }
+///
+/// unsafe impl<K, V> UnsafeUnpin for Struct<K, V> where K: Unpin + Clone {}
+/// ```
+///
+/// [`PhantomPinned`]: core::marker::PhantomPinned
+/// [cargo-geiger]: https://github.com/rust-secure-code/cargo-geiger
+/// [pin-projection]: core::pin#projections-and-structural-pinning
+/// [undefined-behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+pub unsafe trait UnsafeUnpin {}
+
+// Not public API.
+#[doc(hidden)]
+pub mod __private {
+    use core::mem::ManuallyDrop;
+    #[doc(hidden)]
+    pub use core::{
+        marker::{PhantomData, PhantomPinned, Unpin},
+        ops::Drop,
+        pin::Pin,
+        ptr,
+    };
+
+    #[doc(hidden)]
+    pub use pin_project_internal::__PinProjectInternalDerive;
+
+    use super::UnsafeUnpin;
+
+    // An internal trait used for custom implementations of [`Drop`].
+    //
+    // **Do not call or implement this trait directly.**
+    //
+    // # Why this trait is private and `#[pinned_drop]` attribute is needed?
+    //
+    // 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][rust-lang/rust#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,
+    // this crate prevent users from calling `PinnedDrop::drop` in safe code.
+    //
+    // This allows implementing [`Drop`] safely using `#[pinned_drop]`.
+    // Also by using the [`drop`] function just like dropping a type that directly
+    // implements [`Drop`], can drop safely a type that implements `PinnedDrop`.
+    //
+    // [rust-lang/rust#62360]: https://github.com/rust-lang/rust/pull/62360
+    #[doc(hidden)]
+    pub trait PinnedDrop {
+        #[doc(hidden)]
+        unsafe fn drop(self: Pin<&mut Self>);
+    }
+
+    // This is an internal helper struct used by `pin-project-internal`.
+    // This allows us to force an error if the user tries to provide
+    // a regular `Unpin` impl when they specify the `UnsafeUnpin` argument.
+    // This is why we need Wrapper:
+    //
+    // Supposed we have the following code:
+    //
+    // ```rust
+    // #[pin_project(UnsafeUnpin)]
+    // struct MyStruct<T> {
+    //     #[pin] field: T
+    // }
+    //
+    // impl<T> Unpin for MyStruct<T> where MyStruct<T>: UnsafeUnpin {} // generated by pin-project-internal
+    // impl<T> Unpin for MyStruct<T> where T: Copy // written by the user
+    // ```
+    //
+    // We want this code to be rejected - the user is completely bypassing
+    // `UnsafeUnpin`, and providing an unsound Unpin impl in safe code!
+    //
+    // Unfortunately, the Rust compiler will accept the above code.
+    // Because MyStruct is declared in the same crate as the user-provided impl,
+    // the compiler will notice that `MyStruct<T>: UnsafeUnpin` never holds.
+    //
+    // The solution is to introduce the `Wrapper` struct, which is defined
+    // in the `pin-project` crate.
+    //
+    // We now have code that looks like this:
+    //
+    // ```rust
+    // impl<T> Unpin for MyStruct<T> where Wrapper<MyStruct<T>>: UnsafeUnpin {} // generated by pin-project-internal
+    // impl<T> Unpin for MyStruct<T> where T: Copy // written by the user
+    // ```
+    //
+    // We also have `unsafe impl<T> UnsafeUnpin for Wrapper<T> where T: UnsafeUnpin {}`
+    // in the `pin-project` crate.
+    //
+    // Now, our generated impl has a bound involving a type defined in another
+    // crate - Wrapper. This will cause rust to conservatively assume that
+    // `Wrapper<MyStruct<T>>: UnsafeUnpin` holds, in the interest of preserving
+    // forwards compatibility (in case such an impl is added for Wrapper<T> in
+    // a new version of the crate).
+    //
+    // This will cause rust to reject any other `Unpin` impls for MyStruct<T>,
+    // since it will assume that our generated impl could potentially apply in
+    // any situation.
+    //
+    // This achieves the desired effect - when the user writes
+    // `#[pin_project(UnsafeUnpin)]`, the user must either provide no impl of
+    // `UnsafeUnpin` (which is equivalent to making the type never implement
+    // Unpin), or provide an impl of `UnsafeUnpin`. It is impossible for them to
+    // provide an impl of `Unpin`
+    #[doc(hidden)]
+    pub struct Wrapper<'a, T: ?Sized>(PhantomData<&'a ()>, T);
+
+    // SAFETY: `T` implements UnsafeUnpin.
+    unsafe impl<T: ?Sized + UnsafeUnpin> UnsafeUnpin for Wrapper<'_, T> {}
+
+    // This is an internal helper struct used by `pin-project-internal`.
+    //
+    // See https://github.com/taiki-e/pin-project/pull/53 for more details.
+    #[doc(hidden)]
+    pub struct AlwaysUnpin<'a, T>(PhantomData<&'a ()>, PhantomData<T>);
+
+    impl<T> Unpin for AlwaysUnpin<'_, T> {}
+
+    // This is an internal helper used to ensure a value is dropped.
+    #[doc(hidden)]
+    pub struct UnsafeDropInPlaceGuard<T: ?Sized>(*mut T);
+
+    impl<T: ?Sized> UnsafeDropInPlaceGuard<T> {
+        #[doc(hidden)]
+        pub unsafe fn new(ptr: *mut T) -> Self {
+            Self(ptr)
+        }
+    }
+
+    impl<T: ?Sized> Drop for UnsafeDropInPlaceGuard<T> {
+        fn drop(&mut self) {
+            // SAFETY: the caller of `UnsafeDropInPlaceGuard::new` must guarantee
+            // that `ptr` is valid for drop when this guard is destructed.
+            unsafe {
+                ptr::drop_in_place(self.0);
+            }
+        }
+    }
+
+    // This is an internal helper used to ensure a value is overwritten without
+    // its destructor being called.
+    #[doc(hidden)]
+    pub struct UnsafeOverwriteGuard<T> {
+        target: *mut T,
+        value: ManuallyDrop<T>,
+    }
+
+    impl<T> UnsafeOverwriteGuard<T> {
+        #[doc(hidden)]
+        pub unsafe fn new(target: *mut T, value: T) -> Self {
+            Self { target, value: ManuallyDrop::new(value) }
+        }
+    }
+
+    impl<T> Drop for UnsafeOverwriteGuard<T> {
+        fn drop(&mut self) {
+            // SAFETY: the caller of `UnsafeOverwriteGuard::new` must guarantee
+            // that `target` is valid for writes when this guard is destructed.
+            unsafe {
+                ptr::write(self.target, ptr::read(&*self.value));
+            }
+        }
+    }
+}
diff --git a/tests/README.md b/tests/README.md
new file mode 100644 (file)
index 0000000..b109e71
--- /dev/null
@@ -0,0 +1,44 @@
+# Tests
+
+To run all tests, run the following command:
+
+```sh
+cargo +nightly test --all
+```
+
+## UI tests (`ui`, `compiletest.rs`)
+
+This checks errors detected by the macro or the Rust compiler in the resulting
+expanded code.
+
+To run this test, run the following command:
+
+```sh
+cargo +nightly test --test compiletest
+```
+
+Locally, this test updates the files in the `ui` directory if there are
+changes to the generated code. If there are any changes to the files in the
+`ui` directory after running the test, please commit them.
+
+See also [`trybuild` documentation](https://docs.rs/trybuild).
+
+## Expansion tests (`expand`, `expandtest.rs`)
+
+Similar to ui tests, but instead of checking the compiler output, this checks
+the code generated by macros.
+
+See [examples](../examples/README.md) for descriptions of what the generated
+code does, and why it needs to be generated.
+
+To run this test, run the following command:
+
+```sh
+cargo +nightly test --test expandtest
+```
+
+Locally, this test updates the files in the `expand` directory if there are
+changes to the generated code. If there are any changes to the files in the
+`expand` directory after running the test, please commit them.
+
+See also [`macrotest` documentation](https://docs.rs/macrotest).
diff --git a/tests/auxiliary/mod.rs b/tests/auxiliary/mod.rs
new file mode 100644 (file)
index 0000000..1457099
--- /dev/null
@@ -0,0 +1,12 @@
+#![allow(dead_code, unused_macros)]
+
+macro_rules! assert_unpin {
+    ($ty:ty) => {
+        static_assertions::assert_impl_all!($ty: Unpin);
+    };
+}
+macro_rules! assert_not_unpin {
+    ($ty:ty) => {
+        static_assertions::assert_not_impl_all!($ty: Unpin);
+    };
+}
diff --git a/tests/cfg.rs b/tests/cfg.rs
new file mode 100644 (file)
index 0000000..2f5387b
--- /dev/null
@@ -0,0 +1,184 @@
+#![warn(rust_2018_idioms, single_use_lifetimes)]
+#![allow(dead_code)]
+
+// Refs: https://doc.rust-lang.org/reference/attributes.html
+
+#[macro_use]
+mod auxiliary;
+
+use std::{marker::PhantomPinned, pin::Pin};
+
+use pin_project::pin_project;
+
+struct Always;
+
+// Use this type to check that `cfg(any())` is working properly.
+struct Never(PhantomPinned);
+
+#[test]
+fn cfg() {
+    // structs
+
+    #[pin_project(project_replace)]
+    struct SameName {
+        #[cfg(not(any()))]
+        #[pin]
+        inner: Always,
+        #[cfg(any())]
+        #[pin]
+        inner: Never,
+    }
+
+    assert_unpin!(SameName);
+
+    let _ = SameName { inner: Always };
+
+    #[pin_project(project_replace)]
+    struct DifferentName {
+        #[cfg(not(any()))]
+        #[pin]
+        a: Always,
+        #[cfg(any())]
+        #[pin]
+        n: Never,
+    }
+
+    assert_unpin!(DifferentName);
+
+    let _ = DifferentName { a: Always };
+
+    #[pin_project(project_replace)]
+    struct TupleStruct(
+        #[cfg(not(any()))]
+        #[pin]
+        Always,
+        #[cfg(any())]
+        #[pin]
+        Never,
+    );
+
+    assert_unpin!(TupleStruct);
+
+    let _ = TupleStruct(Always);
+
+    // enums
+
+    #[pin_project(
+        project = VariantProj,
+        project_ref = VariantProjRef,
+        project_replace = VariantProjOwn,
+    )]
+    enum Variant {
+        #[cfg(not(any()))]
+        Inner(#[pin] Always),
+        #[cfg(any())]
+        Inner(#[pin] Never),
+
+        #[cfg(not(any()))]
+        A(#[pin] Always),
+        #[cfg(any())]
+        N(#[pin] Never),
+    }
+
+    assert_unpin!(Variant);
+
+    let _ = Variant::Inner(Always);
+    let _ = Variant::A(Always);
+
+    #[pin_project(
+        project = FieldProj,
+        project_ref = FieldProjRef,
+        project_replace = FieldProjOwn,
+    )]
+    enum Field {
+        SameName {
+            #[cfg(not(any()))]
+            #[pin]
+            inner: Always,
+            #[cfg(any())]
+            #[pin]
+            inner: Never,
+        },
+        DifferentName {
+            #[cfg(not(any()))]
+            #[pin]
+            a: Always,
+            #[cfg(any())]
+            #[pin]
+            n: Never,
+        },
+        TupleVariant(
+            #[cfg(not(any()))]
+            #[pin]
+            Always,
+            #[cfg(any())]
+            #[pin]
+            Never,
+        ),
+    }
+
+    assert_unpin!(Field);
+
+    let _ = Field::SameName { inner: Always };
+    let _ = Field::DifferentName { a: Always };
+    let _ = Field::TupleVariant(Always);
+}
+
+#[test]
+fn cfg_attr() {
+    #[pin_project(project_replace)]
+    struct SameCfg {
+        #[cfg(not(any()))]
+        #[cfg_attr(not(any()), pin)]
+        inner: Always,
+        #[cfg(any())]
+        #[cfg_attr(any(), pin)]
+        inner: Never,
+    }
+
+    assert_unpin!(SameCfg);
+
+    let mut x = SameCfg { inner: Always };
+    let x = Pin::new(&mut x).project();
+    let _: Pin<&mut Always> = x.inner;
+
+    #[pin_project(project_replace)]
+    struct DifferentCfg {
+        #[cfg(not(any()))]
+        #[cfg_attr(any(), pin)]
+        inner: Always,
+        #[cfg(any())]
+        #[cfg_attr(not(any()), pin)]
+        inner: Never,
+    }
+
+    assert_unpin!(DifferentCfg);
+
+    let mut x = DifferentCfg { inner: Always };
+    let x = Pin::new(&mut x).project();
+    let _: &mut Always = x.inner;
+
+    #[cfg_attr(not(any()), pin_project)]
+    struct Foo<T> {
+        #[cfg_attr(not(any()), pin)]
+        inner: T,
+    }
+
+    assert_unpin!(Foo<()>);
+    assert_not_unpin!(Foo<PhantomPinned>);
+
+    let mut x = Foo { inner: 0_u8 };
+    let x = Pin::new(&mut x).project();
+    let _: Pin<&mut u8> = x.inner;
+}
+
+#[test]
+fn cfg_attr_any_packed() {
+    // Since `cfg(any())` can never be true, it is okay for this to pass.
+    #[pin_project(project_replace)]
+    #[cfg_attr(any(), repr(packed))]
+    struct Struct {
+        #[pin]
+        f: u32,
+    }
+}
diff --git a/tests/compiletest.rs b/tests/compiletest.rs
new file mode 100644 (file)
index 0000000..b06e1e8
--- /dev/null
@@ -0,0 +1,16 @@
+#![cfg(not(miri))]
+#![warn(rust_2018_idioms, single_use_lifetimes)]
+
+use std::env;
+
+#[rustversion::attr(not(nightly), ignore)]
+#[test]
+fn ui() {
+    if env::var_os("CI").is_none() {
+        env::set_var("TRYBUILD", "overwrite");
+    }
+
+    let t = trybuild::TestCases::new();
+    t.compile_fail("tests/ui/**/*.rs");
+    t.pass("tests/run-pass/**/*.rs");
+}
diff --git a/tests/drop_order.rs b/tests/drop_order.rs
new file mode 100644 (file)
index 0000000..8ced56e
--- /dev/null
@@ -0,0 +1,162 @@
+#![warn(rust_2018_idioms, single_use_lifetimes)]
+
+// Refs: https://doc.rust-lang.org/reference/destructors.html
+
+use std::{cell::Cell, pin::Pin, thread};
+
+use pin_project::pin_project;
+
+struct D<'a>(&'a Cell<usize>, usize);
+
+impl Drop for D<'_> {
+    fn drop(&mut self) {
+        if !thread::panicking() {
+            let old = self.0.replace(self.1);
+            assert_eq!(old, self.1 - 1);
+        }
+    }
+}
+
+#[pin_project(project_replace)]
+struct StructPinned<'a> {
+    #[pin]
+    f1: D<'a>,
+    #[pin]
+    f2: D<'a>,
+}
+
+#[pin_project(project_replace)]
+struct StructUnpinned<'a> {
+    f1: D<'a>,
+    f2: D<'a>,
+}
+
+#[pin_project(project_replace)]
+struct TuplePinned<'a>(#[pin] D<'a>, #[pin] D<'a>);
+
+#[pin_project(project_replace)]
+struct TupleUnpinned<'a>(D<'a>, D<'a>);
+
+#[pin_project(project_replace = EnumProj)]
+enum Enum<'a> {
+    #[allow(dead_code)] // false positive that fixed in Rust 1.38
+    StructPinned {
+        #[pin]
+        f1: D<'a>,
+        #[pin]
+        f2: D<'a>,
+    },
+    #[allow(dead_code)] // false positive that fixed in Rust 1.38
+    StructUnpinned {
+        f1: D<'a>,
+        f2: D<'a>,
+    },
+    TuplePinned(#[pin] D<'a>, #[pin] D<'a>),
+    TupleUnpinned(D<'a>, D<'a>),
+}
+
+#[test]
+fn struct_pinned() {
+    {
+        let c = Cell::new(0);
+        let _x = StructPinned { f1: D(&c, 1), f2: D(&c, 2) };
+    }
+    {
+        let c = Cell::new(0);
+        let mut x = StructPinned { f1: D(&c, 1), f2: D(&c, 2) };
+        let y = Pin::new(&mut x);
+        let _z = y.project_replace(StructPinned { f1: D(&c, 3), f2: D(&c, 4) });
+    }
+}
+
+#[test]
+fn struct_unpinned() {
+    {
+        let c = Cell::new(0);
+        let _x = StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) };
+    }
+    {
+        let c = Cell::new(0);
+        let mut x = StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) };
+        let y = Pin::new(&mut x);
+        let _z = y.project_replace(StructUnpinned { f1: D(&c, 3), f2: D(&c, 4) });
+    }
+}
+
+#[test]
+fn tuple_pinned() {
+    {
+        let c = Cell::new(0);
+        let _x = TuplePinned(D(&c, 1), D(&c, 2));
+    }
+    {
+        let c = Cell::new(0);
+        let mut x = TuplePinned(D(&c, 1), D(&c, 2));
+        let y = Pin::new(&mut x);
+        let _z = y.project_replace(TuplePinned(D(&c, 3), D(&c, 4)));
+    }
+}
+
+#[test]
+fn tuple_unpinned() {
+    {
+        let c = Cell::new(0);
+        let _x = TupleUnpinned(D(&c, 1), D(&c, 2));
+    }
+    {
+        let c = Cell::new(0);
+        let mut x = TupleUnpinned(D(&c, 1), D(&c, 2));
+        let y = Pin::new(&mut x);
+        let _z = y.project_replace(TupleUnpinned(D(&c, 3), D(&c, 4)));
+    }
+}
+
+#[test]
+fn enum_struct() {
+    {
+        let c = Cell::new(0);
+        let _x = Enum::StructPinned { f1: D(&c, 1), f2: D(&c, 2) };
+    }
+    {
+        let c = Cell::new(0);
+        let mut x = Enum::StructPinned { f1: D(&c, 1), f2: D(&c, 2) };
+        let y = Pin::new(&mut x);
+        let _z = y.project_replace(Enum::StructPinned { f1: D(&c, 3), f2: D(&c, 4) });
+    }
+
+    {
+        let c = Cell::new(0);
+        let _x = Enum::StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) };
+    }
+    {
+        let c = Cell::new(0);
+        let mut x = Enum::StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) };
+        let y = Pin::new(&mut x);
+        let _z = y.project_replace(Enum::StructUnpinned { f1: D(&c, 3), f2: D(&c, 4) });
+    }
+}
+
+#[test]
+fn enum_tuple() {
+    {
+        let c = Cell::new(0);
+        let _x = Enum::TuplePinned(D(&c, 1), D(&c, 2));
+    }
+    {
+        let c = Cell::new(0);
+        let mut x = Enum::TuplePinned(D(&c, 1), D(&c, 2));
+        let y = Pin::new(&mut x);
+        let _z = y.project_replace(Enum::TuplePinned(D(&c, 3), D(&c, 4)));
+    }
+
+    {
+        let c = Cell::new(0);
+        let _x = Enum::TupleUnpinned(D(&c, 1), D(&c, 2));
+    }
+    {
+        let c = Cell::new(0);
+        let mut x = Enum::TupleUnpinned(D(&c, 1), D(&c, 2));
+        let y = Pin::new(&mut x);
+        let _z = y.project_replace(Enum::TupleUnpinned(D(&c, 3), D(&c, 4)));
+    }
+}
diff --git a/tests/expand/default/enum.expanded.rs b/tests/expand/default/enum.expanded.rs
new file mode 100644 (file)
index 0000000..490bf2e
--- /dev/null
@@ -0,0 +1,145 @@
+use pin_project::pin_project;
+#[pin(__private(project = EnumProj, project_ref = EnumProjRef))]
+enum Enum<T, U> {
+    Struct { #[pin] pinned: T, unpinned: U },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+enum EnumProj<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Struct {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    },
+    Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+enum EnumProjRef<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Struct { pinned: ::pin_project::__private::Pin<&'pin (T)>, unpinned: &'pin (U) },
+    Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    impl<T, U> Enum<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> EnumProj<'pin, T, U> {
+            unsafe {
+                match self.get_unchecked_mut() {
+                    Self::Struct { pinned, unpinned } => {
+                        EnumProj::Struct {
+                            pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                            unpinned,
+                        }
+                    }
+                    Self::Tuple(_0, _1) => {
+                        EnumProj::Tuple(
+                            _pin_project::__private::Pin::new_unchecked(_0),
+                            _1,
+                        )
+                    }
+                    Self::Unit => EnumProj::Unit,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> EnumProjRef<'pin, T, U> {
+            unsafe {
+                match self.get_ref() {
+                    Self::Struct { pinned, unpinned } => {
+                        EnumProjRef::Struct {
+                            pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                            unpinned,
+                        }
+                    }
+                    Self::Tuple(_0, _1) => {
+                        EnumProjRef::Tuple(
+                            _pin_project::__private::Pin::new_unchecked(_0),
+                            _1,
+                        )
+                    }
+                    Self::Unit => EnumProjRef::Unit,
+                }
+            }
+        }
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Enum<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+        __field1: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait EnumMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> EnumMustNotImplDrop for T {}
+    impl<T, U> EnumMustNotImplDrop for Enum<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Enum<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/default/enum.rs b/tests/expand/default/enum.rs
new file mode 100644 (file)
index 0000000..ff05615
--- /dev/null
@@ -0,0 +1,14 @@
+use pin_project::pin_project;
+
+#[pin_project(project = EnumProj, project_ref = EnumProjRef)]
+enum Enum<T, U> {
+    Struct {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+
+fn main() {}
diff --git a/tests/expand/default/struct.expanded.rs b/tests/expand/default/struct.expanded.rs
new file mode 100644 (file)
index 0000000..0005d86
--- /dev/null
@@ -0,0 +1,104 @@
+use pin_project::pin_project;
+#[pin(__private())]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __StructProjection<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    }
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __StructProjectionRef<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin (T)>,
+        unpinned: &'pin (U),
+    }
+    impl<T, U> Struct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __StructProjection<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                __StructProjection {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __StructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_ref();
+                __StructProjectionRef {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned;
+        let _ = &this.unpinned;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Struct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait StructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> StructMustNotImplDrop for T {}
+    impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Struct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/default/struct.rs b/tests/expand/default/struct.rs
new file mode 100644 (file)
index 0000000..474f0a1
--- /dev/null
@@ -0,0 +1,10 @@
+use pin_project::pin_project;
+
+#[pin_project]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+
+fn main() {}
diff --git a/tests/expand/default/tuple_struct.expanded.rs b/tests/expand/default/tuple_struct.expanded.rs
new file mode 100644 (file)
index 0000000..1c5e3b0
--- /dev/null
@@ -0,0 +1,98 @@
+use pin_project::pin_project;
+#[pin(__private())]
+struct TupleStruct<T, U>(#[pin] T, U);
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __TupleStructProjection<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin mut (T)>,
+        &'pin mut (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __TupleStructProjectionRef<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    impl<T, U> TupleStruct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __TupleStructProjection<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_unchecked_mut();
+                __TupleStructProjection(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __TupleStructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_ref();
+                __TupleStructProjectionRef(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
+        let _ = &this.0;
+        let _ = &this.1;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __TupleStruct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait TupleStructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> TupleStructMustNotImplDrop for T {}
+    impl<T, U> TupleStructMustNotImplDrop for TupleStruct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for TupleStruct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/default/tuple_struct.rs b/tests/expand/default/tuple_struct.rs
new file mode 100644 (file)
index 0000000..398b14f
--- /dev/null
@@ -0,0 +1,6 @@
+use pin_project::pin_project;
+
+#[pin_project]
+struct TupleStruct<T, U>(#[pin] T, U);
+
+fn main() {}
diff --git a/tests/expand/multifields/enum.expanded.rs b/tests/expand/multifields/enum.expanded.rs
new file mode 100644 (file)
index 0000000..8223de3
--- /dev/null
@@ -0,0 +1,268 @@
+use pin_project::pin_project;
+#[pin(
+    __private(
+        project = EnumProj,
+        project_ref = EnumProjRef,
+        project_replace = EnumProjOwn
+    )
+)]
+enum Enum<T, U> {
+    Struct { #[pin] pinned1: T, #[pin] pinned2: T, unpinned1: U, unpinned2: U },
+    Tuple(#[pin] T, #[pin] T, U, U),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+enum EnumProj<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Struct {
+        pinned1: ::pin_project::__private::Pin<&'pin mut (T)>,
+        pinned2: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned1: &'pin mut (U),
+        unpinned2: &'pin mut (U),
+    },
+    Tuple(
+        ::pin_project::__private::Pin<&'pin mut (T)>,
+        ::pin_project::__private::Pin<&'pin mut (T)>,
+        &'pin mut (U),
+        &'pin mut (U),
+    ),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+enum EnumProjRef<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Struct {
+        pinned1: ::pin_project::__private::Pin<&'pin (T)>,
+        pinned2: ::pin_project::__private::Pin<&'pin (T)>,
+        unpinned1: &'pin (U),
+        unpinned2: &'pin (U),
+    },
+    Tuple(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+        &'pin (U),
+    ),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(variant_size_differences)]
+#[allow(clippy::large_enum_variant)]
+enum EnumProjOwn<T, U> {
+    Struct {
+        pinned1: ::pin_project::__private::PhantomData<T>,
+        pinned2: ::pin_project::__private::PhantomData<T>,
+        unpinned1: U,
+        unpinned2: U,
+    },
+    Tuple(
+        ::pin_project::__private::PhantomData<T>,
+        ::pin_project::__private::PhantomData<T>,
+        U,
+        U,
+    ),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    impl<T, U> Enum<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> EnumProj<'pin, T, U> {
+            unsafe {
+                match self.get_unchecked_mut() {
+                    Self::Struct { pinned1, pinned2, unpinned1, unpinned2 } => {
+                        EnumProj::Struct {
+                            pinned1: _pin_project::__private::Pin::new_unchecked(
+                                pinned1,
+                            ),
+                            pinned2: _pin_project::__private::Pin::new_unchecked(
+                                pinned2,
+                            ),
+                            unpinned1,
+                            unpinned2,
+                        }
+                    }
+                    Self::Tuple(_0, _1, _2, _3) => {
+                        EnumProj::Tuple(
+                            _pin_project::__private::Pin::new_unchecked(_0),
+                            _pin_project::__private::Pin::new_unchecked(_1),
+                            _2,
+                            _3,
+                        )
+                    }
+                    Self::Unit => EnumProj::Unit,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> EnumProjRef<'pin, T, U> {
+            unsafe {
+                match self.get_ref() {
+                    Self::Struct { pinned1, pinned2, unpinned1, unpinned2 } => {
+                        EnumProjRef::Struct {
+                            pinned1: _pin_project::__private::Pin::new_unchecked(
+                                pinned1,
+                            ),
+                            pinned2: _pin_project::__private::Pin::new_unchecked(
+                                pinned2,
+                            ),
+                            unpinned1,
+                            unpinned2,
+                        }
+                    }
+                    Self::Tuple(_0, _1, _2, _3) => {
+                        EnumProjRef::Tuple(
+                            _pin_project::__private::Pin::new_unchecked(_0),
+                            _pin_project::__private::Pin::new_unchecked(_1),
+                            _2,
+                            _3,
+                        )
+                    }
+                    Self::Unit => EnumProjRef::Unit,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        fn project_replace(
+            self: _pin_project::__private::Pin<&mut Self>,
+            __replacement: Self,
+        ) -> EnumProjOwn<T, U> {
+            unsafe {
+                let __self_ptr: *mut Self = self.get_unchecked_mut();
+                let __guard = _pin_project::__private::UnsafeOverwriteGuard::new(
+                    __self_ptr,
+                    __replacement,
+                );
+                match &mut *__self_ptr {
+                    Self::Struct { pinned1, pinned2, unpinned1, unpinned2 } => {
+                        let __result = EnumProjOwn::Struct {
+                            pinned1: _pin_project::__private::PhantomData,
+                            pinned2: _pin_project::__private::PhantomData,
+                            unpinned1: _pin_project::__private::ptr::read(unpinned1),
+                            unpinned2: _pin_project::__private::ptr::read(unpinned2),
+                        };
+                        {
+                            let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                                pinned2,
+                            );
+                            let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                                pinned1,
+                            );
+                        }
+                        __result
+                    }
+                    Self::Tuple(_0, _1, _2, _3) => {
+                        let __result = EnumProjOwn::Tuple(
+                            _pin_project::__private::PhantomData,
+                            _pin_project::__private::PhantomData,
+                            _pin_project::__private::ptr::read(_2),
+                            _pin_project::__private::ptr::read(_3),
+                        );
+                        {
+                            let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                                _1,
+                            );
+                            let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                                _0,
+                            );
+                        }
+                        __result
+                    }
+                    Self::Unit => {
+                        let __result = EnumProjOwn::Unit;
+                        {}
+                        __result
+                    }
+                }
+            }
+        }
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Enum<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+        __field1: T,
+        __field2: T,
+        __field3: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait EnumMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> EnumMustNotImplDrop for T {}
+    impl<T, U> EnumMustNotImplDrop for Enum<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Enum<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/multifields/enum.rs b/tests/expand/multifields/enum.rs
new file mode 100644 (file)
index 0000000..754d48c
--- /dev/null
@@ -0,0 +1,17 @@
+use pin_project::pin_project;
+
+#[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
+enum Enum<T, U> {
+    Struct {
+        #[pin]
+        pinned1: T,
+        #[pin]
+        pinned2: T,
+        unpinned1: U,
+        unpinned2: U,
+    },
+    Tuple(#[pin] T, #[pin] T, U, U),
+    Unit,
+}
+
+fn main() {}
diff --git a/tests/expand/multifields/struct.expanded.rs b/tests/expand/multifields/struct.expanded.rs
new file mode 100644 (file)
index 0000000..df8dc92
--- /dev/null
@@ -0,0 +1,155 @@
+use pin_project::pin_project;
+#[pin(__private(project_replace))]
+struct Struct<T, U> {
+    #[pin]
+    pinned1: T,
+    #[pin]
+    pinned2: T,
+    unpinned1: U,
+    unpinned2: U,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __StructProjection<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned1: ::pin_project::__private::Pin<&'pin mut (T)>,
+        pinned2: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned1: &'pin mut (U),
+        unpinned2: &'pin mut (U),
+    }
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __StructProjectionRef<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned1: ::pin_project::__private::Pin<&'pin (T)>,
+        pinned2: ::pin_project::__private::Pin<&'pin (T)>,
+        unpinned1: &'pin (U),
+        unpinned2: &'pin (U),
+    }
+    #[allow(dead_code)]
+    struct __StructProjectionOwned<T, U> {
+        pinned1: ::pin_project::__private::PhantomData<T>,
+        pinned2: ::pin_project::__private::PhantomData<T>,
+        unpinned1: U,
+        unpinned2: U,
+    }
+    impl<T, U> Struct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __StructProjection<'pin, T, U> {
+            unsafe {
+                let Self { pinned1, pinned2, unpinned1, unpinned2 } = self
+                    .get_unchecked_mut();
+                __StructProjection {
+                    pinned1: _pin_project::__private::Pin::new_unchecked(pinned1),
+                    pinned2: _pin_project::__private::Pin::new_unchecked(pinned2),
+                    unpinned1,
+                    unpinned2,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __StructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self { pinned1, pinned2, unpinned1, unpinned2 } = self.get_ref();
+                __StructProjectionRef {
+                    pinned1: _pin_project::__private::Pin::new_unchecked(pinned1),
+                    pinned2: _pin_project::__private::Pin::new_unchecked(pinned2),
+                    unpinned1,
+                    unpinned2,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        fn project_replace(
+            self: _pin_project::__private::Pin<&mut Self>,
+            __replacement: Self,
+        ) -> __StructProjectionOwned<T, U> {
+            unsafe {
+                let __self_ptr: *mut Self = self.get_unchecked_mut();
+                let __guard = _pin_project::__private::UnsafeOverwriteGuard::new(
+                    __self_ptr,
+                    __replacement,
+                );
+                let Self { pinned1, pinned2, unpinned1, unpinned2 } = &mut *__self_ptr;
+                let __result = __StructProjectionOwned {
+                    pinned1: _pin_project::__private::PhantomData,
+                    pinned2: _pin_project::__private::PhantomData,
+                    unpinned1: _pin_project::__private::ptr::read(unpinned1),
+                    unpinned2: _pin_project::__private::ptr::read(unpinned2),
+                };
+                {
+                    let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                        pinned2,
+                    );
+                    let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                        pinned1,
+                    );
+                }
+                __result
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned1;
+        let _ = &this.pinned2;
+        let _ = &this.unpinned1;
+        let _ = &this.unpinned2;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Struct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+        __field1: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait StructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> StructMustNotImplDrop for T {}
+    impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Struct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/multifields/struct.rs b/tests/expand/multifields/struct.rs
new file mode 100644 (file)
index 0000000..3b319bf
--- /dev/null
@@ -0,0 +1,13 @@
+use pin_project::pin_project;
+
+#[pin_project(project_replace)]
+struct Struct<T, U> {
+    #[pin]
+    pinned1: T,
+    #[pin]
+    pinned2: T,
+    unpinned1: U,
+    unpinned2: U,
+}
+
+fn main() {}
diff --git a/tests/expand/multifields/tuple_struct.expanded.rs b/tests/expand/multifields/tuple_struct.expanded.rs
new file mode 100644 (file)
index 0000000..0c85f9a
--- /dev/null
@@ -0,0 +1,145 @@
+use pin_project::pin_project;
+#[pin(__private(project_replace))]
+struct TupleStruct<T, U>(#[pin] T, #[pin] T, U, U);
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __TupleStructProjection<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin mut (T)>,
+        ::pin_project::__private::Pin<&'pin mut (T)>,
+        &'pin mut (U),
+        &'pin mut (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __TupleStructProjectionRef<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+        &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    #[allow(dead_code)]
+    struct __TupleStructProjectionOwned<T, U>(
+        ::pin_project::__private::PhantomData<T>,
+        ::pin_project::__private::PhantomData<T>,
+        U,
+        U,
+    );
+    impl<T, U> TupleStruct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __TupleStructProjection<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1, _2, _3) = self.get_unchecked_mut();
+                __TupleStructProjection(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _pin_project::__private::Pin::new_unchecked(_1),
+                    _2,
+                    _3,
+                )
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __TupleStructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1, _2, _3) = self.get_ref();
+                __TupleStructProjectionRef(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _pin_project::__private::Pin::new_unchecked(_1),
+                    _2,
+                    _3,
+                )
+            }
+        }
+        #[allow(dead_code)]
+        fn project_replace(
+            self: _pin_project::__private::Pin<&mut Self>,
+            __replacement: Self,
+        ) -> __TupleStructProjectionOwned<T, U> {
+            unsafe {
+                let __self_ptr: *mut Self = self.get_unchecked_mut();
+                let __guard = _pin_project::__private::UnsafeOverwriteGuard::new(
+                    __self_ptr,
+                    __replacement,
+                );
+                let Self(_0, _1, _2, _3) = &mut *__self_ptr;
+                let __result = __TupleStructProjectionOwned(
+                    _pin_project::__private::PhantomData,
+                    _pin_project::__private::PhantomData,
+                    _pin_project::__private::ptr::read(_2),
+                    _pin_project::__private::ptr::read(_3),
+                );
+                {
+                    let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                        _1,
+                    );
+                    let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                        _0,
+                    );
+                }
+                __result
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
+        let _ = &this.0;
+        let _ = &this.1;
+        let _ = &this.2;
+        let _ = &this.3;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __TupleStruct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+        __field1: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait TupleStructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> TupleStructMustNotImplDrop for T {}
+    impl<T, U> TupleStructMustNotImplDrop for TupleStruct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for TupleStruct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/multifields/tuple_struct.rs b/tests/expand/multifields/tuple_struct.rs
new file mode 100644 (file)
index 0000000..bc92eee
--- /dev/null
@@ -0,0 +1,6 @@
+use pin_project::pin_project;
+
+#[pin_project(project_replace)]
+struct TupleStruct<T, U>(#[pin] T, #[pin] T, U, U);
+
+fn main() {}
diff --git a/tests/expand/naming/enum-all.expanded.rs b/tests/expand/naming/enum-all.expanded.rs
new file mode 100644 (file)
index 0000000..8dbe768
--- /dev/null
@@ -0,0 +1,204 @@
+use pin_project::pin_project;
+#[pin(__private(project = Proj, project_ref = ProjRef, project_replace = ProjOwn))]
+enum Enum<T, U> {
+    Struct { #[pin] pinned: T, unpinned: U },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+enum Proj<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Struct {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    },
+    Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+enum ProjRef<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Struct { pinned: ::pin_project::__private::Pin<&'pin (T)>, unpinned: &'pin (U) },
+    Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(variant_size_differences)]
+#[allow(clippy::large_enum_variant)]
+enum ProjOwn<T, U> {
+    Struct { pinned: ::pin_project::__private::PhantomData<T>, unpinned: U },
+    Tuple(::pin_project::__private::PhantomData<T>, U),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    impl<T, U> Enum<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> Proj<'pin, T, U> {
+            unsafe {
+                match self.get_unchecked_mut() {
+                    Self::Struct { pinned, unpinned } => {
+                        Proj::Struct {
+                            pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                            unpinned,
+                        }
+                    }
+                    Self::Tuple(_0, _1) => {
+                        Proj::Tuple(_pin_project::__private::Pin::new_unchecked(_0), _1)
+                    }
+                    Self::Unit => Proj::Unit,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> ProjRef<'pin, T, U> {
+            unsafe {
+                match self.get_ref() {
+                    Self::Struct { pinned, unpinned } => {
+                        ProjRef::Struct {
+                            pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                            unpinned,
+                        }
+                    }
+                    Self::Tuple(_0, _1) => {
+                        ProjRef::Tuple(
+                            _pin_project::__private::Pin::new_unchecked(_0),
+                            _1,
+                        )
+                    }
+                    Self::Unit => ProjRef::Unit,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        fn project_replace(
+            self: _pin_project::__private::Pin<&mut Self>,
+            __replacement: Self,
+        ) -> ProjOwn<T, U> {
+            unsafe {
+                let __self_ptr: *mut Self = self.get_unchecked_mut();
+                let __guard = _pin_project::__private::UnsafeOverwriteGuard::new(
+                    __self_ptr,
+                    __replacement,
+                );
+                match &mut *__self_ptr {
+                    Self::Struct { pinned, unpinned } => {
+                        let __result = ProjOwn::Struct {
+                            pinned: _pin_project::__private::PhantomData,
+                            unpinned: _pin_project::__private::ptr::read(unpinned),
+                        };
+                        {
+                            let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                                pinned,
+                            );
+                        }
+                        __result
+                    }
+                    Self::Tuple(_0, _1) => {
+                        let __result = ProjOwn::Tuple(
+                            _pin_project::__private::PhantomData,
+                            _pin_project::__private::ptr::read(_1),
+                        );
+                        {
+                            let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                                _0,
+                            );
+                        }
+                        __result
+                    }
+                    Self::Unit => {
+                        let __result = ProjOwn::Unit;
+                        {}
+                        __result
+                    }
+                }
+            }
+        }
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Enum<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+        __field1: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait EnumMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> EnumMustNotImplDrop for T {}
+    impl<T, U> EnumMustNotImplDrop for Enum<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Enum<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/naming/enum-all.rs b/tests/expand/naming/enum-all.rs
new file mode 100644 (file)
index 0000000..dd513e6
--- /dev/null
@@ -0,0 +1,14 @@
+use pin_project::pin_project;
+
+#[pin_project(project = Proj, project_ref = ProjRef, project_replace = ProjOwn)]
+enum Enum<T, U> {
+    Struct {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+
+fn main() {}
diff --git a/tests/expand/naming/enum-mut.expanded.rs b/tests/expand/naming/enum-mut.expanded.rs
new file mode 100644 (file)
index 0000000..c6916ec
--- /dev/null
@@ -0,0 +1,99 @@
+use pin_project::pin_project;
+#[pin(__private(project = Proj))]
+enum Enum<T, U> {
+    Struct { #[pin] pinned: T, unpinned: U },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+enum Proj<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Struct {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    },
+    Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    impl<T, U> Enum<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> Proj<'pin, T, U> {
+            unsafe {
+                match self.get_unchecked_mut() {
+                    Self::Struct { pinned, unpinned } => {
+                        Proj::Struct {
+                            pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                            unpinned,
+                        }
+                    }
+                    Self::Tuple(_0, _1) => {
+                        Proj::Tuple(_pin_project::__private::Pin::new_unchecked(_0), _1)
+                    }
+                    Self::Unit => Proj::Unit,
+                }
+            }
+        }
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Enum<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+        __field1: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait EnumMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> EnumMustNotImplDrop for T {}
+    impl<T, U> EnumMustNotImplDrop for Enum<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Enum<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/naming/enum-mut.rs b/tests/expand/naming/enum-mut.rs
new file mode 100644 (file)
index 0000000..818276f
--- /dev/null
@@ -0,0 +1,14 @@
+use pin_project::pin_project;
+
+#[pin_project(project = Proj)]
+enum Enum<T, U> {
+    Struct {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+
+fn main() {}
diff --git a/tests/expand/naming/enum-none.expanded.rs b/tests/expand/naming/enum-none.expanded.rs
new file mode 100644 (file)
index 0000000..46477d1
--- /dev/null
@@ -0,0 +1,56 @@
+use pin_project::pin_project;
+#[pin(__private())]
+enum Enum<T, U> {
+    Struct { #[pin] pinned: T, unpinned: U },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    impl<T, U> Enum<T, U> {}
+    #[allow(missing_debug_implementations)]
+    struct __Enum<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+        __field1: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait EnumMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> EnumMustNotImplDrop for T {}
+    impl<T, U> EnumMustNotImplDrop for Enum<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Enum<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/naming/enum-none.rs b/tests/expand/naming/enum-none.rs
new file mode 100644 (file)
index 0000000..a87438d
--- /dev/null
@@ -0,0 +1,14 @@
+use pin_project::pin_project;
+
+#[pin_project]
+enum Enum<T, U> {
+    Struct {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+
+fn main() {}
diff --git a/tests/expand/naming/enum-own.expanded.rs b/tests/expand/naming/enum-own.expanded.rs
new file mode 100644 (file)
index 0000000..ddeb00c
--- /dev/null
@@ -0,0 +1,119 @@
+use pin_project::pin_project;
+#[pin(__private(project_replace = ProjOwn))]
+enum Enum<T, U> {
+    Struct { #[pin] pinned: T, unpinned: U },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(variant_size_differences)]
+#[allow(clippy::large_enum_variant)]
+enum ProjOwn<T, U> {
+    Struct { pinned: ::pin_project::__private::PhantomData<T>, unpinned: U },
+    Tuple(::pin_project::__private::PhantomData<T>, U),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    impl<T, U> Enum<T, U> {
+        #[allow(dead_code)]
+        fn project_replace(
+            self: _pin_project::__private::Pin<&mut Self>,
+            __replacement: Self,
+        ) -> ProjOwn<T, U> {
+            unsafe {
+                let __self_ptr: *mut Self = self.get_unchecked_mut();
+                let __guard = _pin_project::__private::UnsafeOverwriteGuard::new(
+                    __self_ptr,
+                    __replacement,
+                );
+                match &mut *__self_ptr {
+                    Self::Struct { pinned, unpinned } => {
+                        let __result = ProjOwn::Struct {
+                            pinned: _pin_project::__private::PhantomData,
+                            unpinned: _pin_project::__private::ptr::read(unpinned),
+                        };
+                        {
+                            let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                                pinned,
+                            );
+                        }
+                        __result
+                    }
+                    Self::Tuple(_0, _1) => {
+                        let __result = ProjOwn::Tuple(
+                            _pin_project::__private::PhantomData,
+                            _pin_project::__private::ptr::read(_1),
+                        );
+                        {
+                            let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                                _0,
+                            );
+                        }
+                        __result
+                    }
+                    Self::Unit => {
+                        let __result = ProjOwn::Unit;
+                        {}
+                        __result
+                    }
+                }
+            }
+        }
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Enum<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+        __field1: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait EnumMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> EnumMustNotImplDrop for T {}
+    impl<T, U> EnumMustNotImplDrop for Enum<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Enum<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/naming/enum-own.rs b/tests/expand/naming/enum-own.rs
new file mode 100644 (file)
index 0000000..cf88697
--- /dev/null
@@ -0,0 +1,14 @@
+use pin_project::pin_project;
+
+#[pin_project(project_replace = ProjOwn)]
+enum Enum<T, U> {
+    Struct {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+
+fn main() {}
diff --git a/tests/expand/naming/enum-ref.expanded.rs b/tests/expand/naming/enum-ref.expanded.rs
new file mode 100644 (file)
index 0000000..1a49584
--- /dev/null
@@ -0,0 +1,100 @@
+use pin_project::pin_project;
+#[pin(__private(project_ref = ProjRef))]
+enum Enum<T, U> {
+    Struct { #[pin] pinned: T, unpinned: U },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+enum ProjRef<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Struct { pinned: ::pin_project::__private::Pin<&'pin (T)>, unpinned: &'pin (U) },
+    Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    impl<T, U> Enum<T, U> {
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> ProjRef<'pin, T, U> {
+            unsafe {
+                match self.get_ref() {
+                    Self::Struct { pinned, unpinned } => {
+                        ProjRef::Struct {
+                            pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                            unpinned,
+                        }
+                    }
+                    Self::Tuple(_0, _1) => {
+                        ProjRef::Tuple(
+                            _pin_project::__private::Pin::new_unchecked(_0),
+                            _1,
+                        )
+                    }
+                    Self::Unit => ProjRef::Unit,
+                }
+            }
+        }
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Enum<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+        __field1: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait EnumMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> EnumMustNotImplDrop for T {}
+    impl<T, U> EnumMustNotImplDrop for Enum<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Enum<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/naming/enum-ref.rs b/tests/expand/naming/enum-ref.rs
new file mode 100644 (file)
index 0000000..b1ff805
--- /dev/null
@@ -0,0 +1,14 @@
+use pin_project::pin_project;
+
+#[pin_project(project_ref = ProjRef)]
+enum Enum<T, U> {
+    Struct {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+
+fn main() {}
diff --git a/tests/expand/naming/struct-all.expanded.rs b/tests/expand/naming/struct-all.expanded.rs
new file mode 100644 (file)
index 0000000..e598a4f
--- /dev/null
@@ -0,0 +1,163 @@
+use pin_project::pin_project;
+#[pin(__private(project = Proj, project_ref = ProjRef, project_replace = ProjOwn))]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+struct Proj<'pin, T, U>
+where
+    Struct<T, U>: 'pin,
+{
+    pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+    unpinned: &'pin mut (U),
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+struct ProjRef<'pin, T, U>
+where
+    Struct<T, U>: 'pin,
+{
+    pinned: ::pin_project::__private::Pin<&'pin (T)>,
+    unpinned: &'pin (U),
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+struct ProjOwn<T, U> {
+    pinned: ::pin_project::__private::PhantomData<T>,
+    unpinned: U,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    impl<T, U> Struct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> Proj<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                Proj {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> ProjRef<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_ref();
+                ProjRef {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        fn project_replace(
+            self: _pin_project::__private::Pin<&mut Self>,
+            __replacement: Self,
+        ) -> ProjOwn<T, U> {
+            unsafe {
+                let __self_ptr: *mut Self = self.get_unchecked_mut();
+                let __guard = _pin_project::__private::UnsafeOverwriteGuard::new(
+                    __self_ptr,
+                    __replacement,
+                );
+                let Self { pinned, unpinned } = &mut *__self_ptr;
+                let __result = ProjOwn {
+                    pinned: _pin_project::__private::PhantomData,
+                    unpinned: _pin_project::__private::ptr::read(unpinned),
+                };
+                {
+                    let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                        pinned,
+                    );
+                }
+                __result
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned;
+        let _ = &this.unpinned;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Struct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait StructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> StructMustNotImplDrop for T {}
+    impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Struct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/naming/struct-all.rs b/tests/expand/naming/struct-all.rs
new file mode 100644 (file)
index 0000000..c229ba4
--- /dev/null
@@ -0,0 +1,10 @@
+use pin_project::pin_project;
+
+#[pin_project(project = Proj, project_ref = ProjRef, project_replace = ProjOwn)]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+
+fn main() {}
diff --git a/tests/expand/naming/struct-mut.expanded.rs b/tests/expand/naming/struct-mut.expanded.rs
new file mode 100644 (file)
index 0000000..88782ee
--- /dev/null
@@ -0,0 +1,114 @@
+use pin_project::pin_project;
+#[pin(__private(project = Proj))]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+struct Proj<'pin, T, U>
+where
+    Struct<T, U>: 'pin,
+{
+    pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+    unpinned: &'pin mut (U),
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __StructProjectionRef<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin (T)>,
+        unpinned: &'pin (U),
+    }
+    impl<T, U> Struct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> Proj<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                Proj {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __StructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_ref();
+                __StructProjectionRef {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned;
+        let _ = &this.unpinned;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Struct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait StructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> StructMustNotImplDrop for T {}
+    impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Struct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/naming/struct-mut.rs b/tests/expand/naming/struct-mut.rs
new file mode 100644 (file)
index 0000000..2f554d3
--- /dev/null
@@ -0,0 +1,10 @@
+use pin_project::pin_project;
+
+#[pin_project(project = Proj)]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+
+fn main() {}
diff --git a/tests/expand/naming/struct-none.expanded.rs b/tests/expand/naming/struct-none.expanded.rs
new file mode 100644 (file)
index 0000000..0005d86
--- /dev/null
@@ -0,0 +1,104 @@
+use pin_project::pin_project;
+#[pin(__private())]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __StructProjection<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    }
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __StructProjectionRef<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin (T)>,
+        unpinned: &'pin (U),
+    }
+    impl<T, U> Struct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __StructProjection<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                __StructProjection {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __StructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_ref();
+                __StructProjectionRef {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned;
+        let _ = &this.unpinned;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Struct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait StructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> StructMustNotImplDrop for T {}
+    impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Struct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/naming/struct-none.rs b/tests/expand/naming/struct-none.rs
new file mode 100644 (file)
index 0000000..474f0a1
--- /dev/null
@@ -0,0 +1,10 @@
+use pin_project::pin_project;
+
+#[pin_project]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+
+fn main() {}
diff --git a/tests/expand/naming/struct-own.expanded.rs b/tests/expand/naming/struct-own.expanded.rs
new file mode 100644 (file)
index 0000000..cc24862
--- /dev/null
@@ -0,0 +1,143 @@
+use pin_project::pin_project;
+#[pin(__private(project_replace = ProjOwn))]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+struct ProjOwn<T, U> {
+    pinned: ::pin_project::__private::PhantomData<T>,
+    unpinned: U,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __StructProjection<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    }
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __StructProjectionRef<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin (T)>,
+        unpinned: &'pin (U),
+    }
+    impl<T, U> Struct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __StructProjection<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                __StructProjection {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __StructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_ref();
+                __StructProjectionRef {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        fn project_replace(
+            self: _pin_project::__private::Pin<&mut Self>,
+            __replacement: Self,
+        ) -> ProjOwn<T, U> {
+            unsafe {
+                let __self_ptr: *mut Self = self.get_unchecked_mut();
+                let __guard = _pin_project::__private::UnsafeOverwriteGuard::new(
+                    __self_ptr,
+                    __replacement,
+                );
+                let Self { pinned, unpinned } = &mut *__self_ptr;
+                let __result = ProjOwn {
+                    pinned: _pin_project::__private::PhantomData,
+                    unpinned: _pin_project::__private::ptr::read(unpinned),
+                };
+                {
+                    let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                        pinned,
+                    );
+                }
+                __result
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned;
+        let _ = &this.unpinned;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Struct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait StructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> StructMustNotImplDrop for T {}
+    impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Struct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/naming/struct-own.rs b/tests/expand/naming/struct-own.rs
new file mode 100644 (file)
index 0000000..4924362
--- /dev/null
@@ -0,0 +1,10 @@
+use pin_project::pin_project;
+
+#[pin_project(project_replace = ProjOwn)]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+
+fn main() {}
diff --git a/tests/expand/naming/struct-ref.expanded.rs b/tests/expand/naming/struct-ref.expanded.rs
new file mode 100644 (file)
index 0000000..e392f6f
--- /dev/null
@@ -0,0 +1,114 @@
+use pin_project::pin_project;
+#[pin(__private(project_ref = ProjRef))]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+struct ProjRef<'pin, T, U>
+where
+    Struct<T, U>: 'pin,
+{
+    pinned: ::pin_project::__private::Pin<&'pin (T)>,
+    unpinned: &'pin (U),
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __StructProjection<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    }
+    impl<T, U> Struct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __StructProjection<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                __StructProjection {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> ProjRef<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_ref();
+                ProjRef {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned;
+        let _ = &this.unpinned;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Struct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait StructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> StructMustNotImplDrop for T {}
+    impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Struct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/naming/struct-ref.rs b/tests/expand/naming/struct-ref.rs
new file mode 100644 (file)
index 0000000..4e29a16
--- /dev/null
@@ -0,0 +1,10 @@
+use pin_project::pin_project;
+
+#[pin_project(project_ref = ProjRef)]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+
+fn main() {}
diff --git a/tests/expand/naming/tuple_struct-all.expanded.rs b/tests/expand/naming/tuple_struct-all.expanded.rs
new file mode 100644 (file)
index 0000000..8c148ed
--- /dev/null
@@ -0,0 +1,148 @@
+use pin_project::pin_project;
+#[pin(__private(project = Proj, project_ref = ProjRef, project_replace = ProjOwn))]
+struct TupleStruct<T, U>(#[pin] T, U);
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+struct Proj<'pin, T, U>(
+    ::pin_project::__private::Pin<&'pin mut (T)>,
+    &'pin mut (U),
+)
+where
+    TupleStruct<T, U>: 'pin;
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+struct ProjRef<'pin, T, U>(
+    ::pin_project::__private::Pin<&'pin (T)>,
+    &'pin (U),
+)
+where
+    TupleStruct<T, U>: 'pin;
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+struct ProjOwn<T, U>(::pin_project::__private::PhantomData<T>, U);
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    impl<T, U> TupleStruct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> Proj<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_unchecked_mut();
+                Proj(_pin_project::__private::Pin::new_unchecked(_0), _1)
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> ProjRef<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_ref();
+                ProjRef(_pin_project::__private::Pin::new_unchecked(_0), _1)
+            }
+        }
+        #[allow(dead_code)]
+        fn project_replace(
+            self: _pin_project::__private::Pin<&mut Self>,
+            __replacement: Self,
+        ) -> ProjOwn<T, U> {
+            unsafe {
+                let __self_ptr: *mut Self = self.get_unchecked_mut();
+                let __guard = _pin_project::__private::UnsafeOverwriteGuard::new(
+                    __self_ptr,
+                    __replacement,
+                );
+                let Self(_0, _1) = &mut *__self_ptr;
+                let __result = ProjOwn(
+                    _pin_project::__private::PhantomData,
+                    _pin_project::__private::ptr::read(_1),
+                );
+                {
+                    let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                        _0,
+                    );
+                }
+                __result
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
+        let _ = &this.0;
+        let _ = &this.1;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __TupleStruct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait TupleStructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> TupleStructMustNotImplDrop for T {}
+    impl<T, U> TupleStructMustNotImplDrop for TupleStruct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for TupleStruct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/naming/tuple_struct-all.rs b/tests/expand/naming/tuple_struct-all.rs
new file mode 100644 (file)
index 0000000..0d95cb0
--- /dev/null
@@ -0,0 +1,6 @@
+use pin_project::pin_project;
+
+#[pin_project(project = Proj, project_ref = ProjRef, project_replace = ProjOwn)]
+struct TupleStruct<T, U>(#[pin] T, U);
+
+fn main() {}
diff --git a/tests/expand/naming/tuple_struct-mut.expanded.rs b/tests/expand/naming/tuple_struct-mut.expanded.rs
new file mode 100644 (file)
index 0000000..79c7901
--- /dev/null
@@ -0,0 +1,105 @@
+use pin_project::pin_project;
+#[pin(__private(project = Proj))]
+struct TupleStruct<T, U>(#[pin] T, U);
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+struct Proj<'pin, T, U>(
+    ::pin_project::__private::Pin<&'pin mut (T)>,
+    &'pin mut (U),
+)
+where
+    TupleStruct<T, U>: 'pin;
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __TupleStructProjectionRef<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    impl<T, U> TupleStruct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> Proj<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_unchecked_mut();
+                Proj(_pin_project::__private::Pin::new_unchecked(_0), _1)
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __TupleStructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_ref();
+                __TupleStructProjectionRef(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
+        let _ = &this.0;
+        let _ = &this.1;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __TupleStruct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait TupleStructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> TupleStructMustNotImplDrop for T {}
+    impl<T, U> TupleStructMustNotImplDrop for TupleStruct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for TupleStruct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/naming/tuple_struct-mut.rs b/tests/expand/naming/tuple_struct-mut.rs
new file mode 100644 (file)
index 0000000..e9779a6
--- /dev/null
@@ -0,0 +1,6 @@
+use pin_project::pin_project;
+
+#[pin_project(project = Proj)]
+struct TupleStruct<T, U>(#[pin] T, U);
+
+fn main() {}
diff --git a/tests/expand/naming/tuple_struct-none.expanded.rs b/tests/expand/naming/tuple_struct-none.expanded.rs
new file mode 100644 (file)
index 0000000..1c5e3b0
--- /dev/null
@@ -0,0 +1,98 @@
+use pin_project::pin_project;
+#[pin(__private())]
+struct TupleStruct<T, U>(#[pin] T, U);
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __TupleStructProjection<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin mut (T)>,
+        &'pin mut (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __TupleStructProjectionRef<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    impl<T, U> TupleStruct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __TupleStructProjection<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_unchecked_mut();
+                __TupleStructProjection(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __TupleStructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_ref();
+                __TupleStructProjectionRef(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
+        let _ = &this.0;
+        let _ = &this.1;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __TupleStruct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait TupleStructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> TupleStructMustNotImplDrop for T {}
+    impl<T, U> TupleStructMustNotImplDrop for TupleStruct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for TupleStruct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/naming/tuple_struct-none.rs b/tests/expand/naming/tuple_struct-none.rs
new file mode 100644 (file)
index 0000000..398b14f
--- /dev/null
@@ -0,0 +1,6 @@
+use pin_project::pin_project;
+
+#[pin_project]
+struct TupleStruct<T, U>(#[pin] T, U);
+
+fn main() {}
diff --git a/tests/expand/naming/tuple_struct-own.expanded.rs b/tests/expand/naming/tuple_struct-own.expanded.rs
new file mode 100644 (file)
index 0000000..37e4c34
--- /dev/null
@@ -0,0 +1,134 @@
+use pin_project::pin_project;
+#[pin(__private(project_replace = ProjOwn))]
+struct TupleStruct<T, U>(#[pin] T, U);
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+struct ProjOwn<T, U>(::pin_project::__private::PhantomData<T>, U);
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __TupleStructProjection<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin mut (T)>,
+        &'pin mut (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __TupleStructProjectionRef<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    impl<T, U> TupleStruct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __TupleStructProjection<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_unchecked_mut();
+                __TupleStructProjection(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __TupleStructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_ref();
+                __TupleStructProjectionRef(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+        #[allow(dead_code)]
+        fn project_replace(
+            self: _pin_project::__private::Pin<&mut Self>,
+            __replacement: Self,
+        ) -> ProjOwn<T, U> {
+            unsafe {
+                let __self_ptr: *mut Self = self.get_unchecked_mut();
+                let __guard = _pin_project::__private::UnsafeOverwriteGuard::new(
+                    __self_ptr,
+                    __replacement,
+                );
+                let Self(_0, _1) = &mut *__self_ptr;
+                let __result = ProjOwn(
+                    _pin_project::__private::PhantomData,
+                    _pin_project::__private::ptr::read(_1),
+                );
+                {
+                    let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                        _0,
+                    );
+                }
+                __result
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
+        let _ = &this.0;
+        let _ = &this.1;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __TupleStruct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait TupleStructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> TupleStructMustNotImplDrop for T {}
+    impl<T, U> TupleStructMustNotImplDrop for TupleStruct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for TupleStruct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/naming/tuple_struct-own.rs b/tests/expand/naming/tuple_struct-own.rs
new file mode 100644 (file)
index 0000000..a15ad40
--- /dev/null
@@ -0,0 +1,6 @@
+use pin_project::pin_project;
+
+#[pin_project(project_replace = ProjOwn)]
+struct TupleStruct<T, U>(#[pin] T, U);
+
+fn main() {}
diff --git a/tests/expand/naming/tuple_struct-ref.expanded.rs b/tests/expand/naming/tuple_struct-ref.expanded.rs
new file mode 100644 (file)
index 0000000..8c86868
--- /dev/null
@@ -0,0 +1,105 @@
+use pin_project::pin_project;
+#[pin(__private(project_ref = ProjRef))]
+struct TupleStruct<T, U>(#[pin] T, U);
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+struct ProjRef<'pin, T, U>(
+    ::pin_project::__private::Pin<&'pin (T)>,
+    &'pin (U),
+)
+where
+    TupleStruct<T, U>: 'pin;
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __TupleStructProjection<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin mut (T)>,
+        &'pin mut (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    impl<T, U> TupleStruct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __TupleStructProjection<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_unchecked_mut();
+                __TupleStructProjection(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> ProjRef<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_ref();
+                ProjRef(_pin_project::__private::Pin::new_unchecked(_0), _1)
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
+        let _ = &this.0;
+        let _ = &this.1;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __TupleStruct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait TupleStructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> TupleStructMustNotImplDrop for T {}
+    impl<T, U> TupleStructMustNotImplDrop for TupleStruct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for TupleStruct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/naming/tuple_struct-ref.rs b/tests/expand/naming/tuple_struct-ref.rs
new file mode 100644 (file)
index 0000000..cc61edf
--- /dev/null
@@ -0,0 +1,6 @@
+use pin_project::pin_project;
+
+#[pin_project(project_ref = ProjRef)]
+struct TupleStruct<T, U>(#[pin] T, U);
+
+fn main() {}
diff --git a/tests/expand/not_unpin/enum.expanded.rs b/tests/expand/not_unpin/enum.expanded.rs
new file mode 100644 (file)
index 0000000..98e7bbe
--- /dev/null
@@ -0,0 +1,139 @@
+use pin_project::pin_project;
+#[pin(__private(!Unpin, project = EnumProj, project_ref = EnumProjRef))]
+enum Enum<T, U> {
+    Struct { #[pin] pinned: T, unpinned: U },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+enum EnumProj<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Struct {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    },
+    Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+enum EnumProjRef<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Struct { pinned: ::pin_project::__private::Pin<&'pin (T)>, unpinned: &'pin (U) },
+    Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    impl<T, U> Enum<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> EnumProj<'pin, T, U> {
+            unsafe {
+                match self.get_unchecked_mut() {
+                    Self::Struct { pinned, unpinned } => {
+                        EnumProj::Struct {
+                            pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                            unpinned,
+                        }
+                    }
+                    Self::Tuple(_0, _1) => {
+                        EnumProj::Tuple(
+                            _pin_project::__private::Pin::new_unchecked(_0),
+                            _1,
+                        )
+                    }
+                    Self::Unit => EnumProj::Unit,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> EnumProjRef<'pin, T, U> {
+            unsafe {
+                match self.get_ref() {
+                    Self::Struct { pinned, unpinned } => {
+                        EnumProjRef::Struct {
+                            pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                            unpinned,
+                        }
+                    }
+                    Self::Tuple(_0, _1) => {
+                        EnumProjRef::Tuple(
+                            _pin_project::__private::Pin::new_unchecked(_0),
+                            _1,
+                        )
+                    }
+                    Self::Unit => EnumProjRef::Unit,
+                }
+            }
+        }
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
+    where
+        _pin_project::__private::Wrapper<
+            'pin,
+            _pin_project::__private::PhantomPinned,
+        >: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
+    where
+        _pin_project::__private::Wrapper<
+            'pin,
+            _pin_project::__private::PhantomPinned,
+        >: _pin_project::__private::Unpin,
+    {}
+    trait EnumMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> EnumMustNotImplDrop for T {}
+    impl<T, U> EnumMustNotImplDrop for Enum<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Enum<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/not_unpin/enum.rs b/tests/expand/not_unpin/enum.rs
new file mode 100644 (file)
index 0000000..ac0b3b8
--- /dev/null
@@ -0,0 +1,14 @@
+use pin_project::pin_project;
+
+#[pin_project(!Unpin, project = EnumProj, project_ref = EnumProjRef)]
+enum Enum<T, U> {
+    Struct {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+
+fn main() {}
diff --git a/tests/expand/not_unpin/struct.expanded.rs b/tests/expand/not_unpin/struct.expanded.rs
new file mode 100644 (file)
index 0000000..420f21a
--- /dev/null
@@ -0,0 +1,99 @@
+use pin_project::pin_project;
+#[pin(__private(!Unpin))]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __StructProjection<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    }
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __StructProjectionRef<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin (T)>,
+        unpinned: &'pin (U),
+    }
+    impl<T, U> Struct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __StructProjection<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                __StructProjection {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __StructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_ref();
+                __StructProjectionRef {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned;
+        let _ = &this.unpinned;
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Struct<T, U>
+    where
+        _pin_project::__private::Wrapper<
+            'pin,
+            _pin_project::__private::PhantomPinned,
+        >: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct<T, U>
+    where
+        _pin_project::__private::Wrapper<
+            'pin,
+            _pin_project::__private::PhantomPinned,
+        >: _pin_project::__private::Unpin,
+    {}
+    trait StructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> StructMustNotImplDrop for T {}
+    impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Struct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/not_unpin/struct.rs b/tests/expand/not_unpin/struct.rs
new file mode 100644 (file)
index 0000000..233e6d4
--- /dev/null
@@ -0,0 +1,10 @@
+use pin_project::pin_project;
+
+#[pin_project(!Unpin)]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+
+fn main() {}
diff --git a/tests/expand/not_unpin/tuple_struct.expanded.rs b/tests/expand/not_unpin/tuple_struct.expanded.rs
new file mode 100644 (file)
index 0000000..99621f4
--- /dev/null
@@ -0,0 +1,93 @@
+use pin_project::pin_project;
+#[pin(__private(!Unpin))]
+struct TupleStruct<T, U>(#[pin] T, U);
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __TupleStructProjection<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin mut (T)>,
+        &'pin mut (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __TupleStructProjectionRef<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    impl<T, U> TupleStruct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __TupleStructProjection<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_unchecked_mut();
+                __TupleStructProjection(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __TupleStructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_ref();
+                __TupleStructProjectionRef(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
+        let _ = &this.0;
+        let _ = &this.1;
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct<T, U>
+    where
+        _pin_project::__private::Wrapper<
+            'pin,
+            _pin_project::__private::PhantomPinned,
+        >: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct<T, U>
+    where
+        _pin_project::__private::Wrapper<
+            'pin,
+            _pin_project::__private::PhantomPinned,
+        >: _pin_project::__private::Unpin,
+    {}
+    trait TupleStructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> TupleStructMustNotImplDrop for T {}
+    impl<T, U> TupleStructMustNotImplDrop for TupleStruct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for TupleStruct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/not_unpin/tuple_struct.rs b/tests/expand/not_unpin/tuple_struct.rs
new file mode 100644 (file)
index 0000000..c8065db
--- /dev/null
@@ -0,0 +1,6 @@
+use pin_project::pin_project;
+
+#[pin_project(!Unpin)]
+struct TupleStruct<T, U>(#[pin] T, U);
+
+fn main() {}
diff --git a/tests/expand/pinned_drop/enum.expanded.rs b/tests/expand/pinned_drop/enum.expanded.rs
new file mode 100644 (file)
index 0000000..1a8e746
--- /dev/null
@@ -0,0 +1,157 @@
+use std::pin::Pin;
+use pin_project::{pin_project, pinned_drop};
+#[pin(__private(PinnedDrop, project = EnumProj, project_ref = EnumProjRef))]
+enum Enum<T, U> {
+    Struct { #[pin] pinned: T, unpinned: U },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+enum EnumProj<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Struct {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    },
+    Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+enum EnumProjRef<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Struct { pinned: ::pin_project::__private::Pin<&'pin (T)>, unpinned: &'pin (U) },
+    Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    impl<T, U> Enum<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> EnumProj<'pin, T, U> {
+            unsafe {
+                match self.get_unchecked_mut() {
+                    Self::Struct { pinned, unpinned } => {
+                        EnumProj::Struct {
+                            pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                            unpinned,
+                        }
+                    }
+                    Self::Tuple(_0, _1) => {
+                        EnumProj::Tuple(
+                            _pin_project::__private::Pin::new_unchecked(_0),
+                            _1,
+                        )
+                    }
+                    Self::Unit => EnumProj::Unit,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> EnumProjRef<'pin, T, U> {
+            unsafe {
+                match self.get_ref() {
+                    Self::Struct { pinned, unpinned } => {
+                        EnumProjRef::Struct {
+                            pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                            unpinned,
+                        }
+                    }
+                    Self::Tuple(_0, _1) => {
+                        EnumProjRef::Tuple(
+                            _pin_project::__private::Pin::new_unchecked(_0),
+                            _1,
+                        )
+                    }
+                    Self::Unit => EnumProjRef::Unit,
+                }
+            }
+        }
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Enum<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+        __field1: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    impl<T, U> _pin_project::__private::Drop for Enum<T, U> {
+        fn drop(&mut self) {
+            unsafe {
+                let __pinned_self = _pin_project::__private::Pin::new_unchecked(self);
+                _pin_project::__private::PinnedDrop::drop(__pinned_self);
+            }
+        }
+    }
+};
+#[doc(hidden)]
+impl<T, U> ::pin_project::__private::PinnedDrop for Enum<T, U> {
+    unsafe fn drop(self: Pin<&mut Self>) {
+        #[allow(clippy::needless_pass_by_value)]
+        fn __drop_inner<T, U>(__self: Pin<&mut Enum<T, U>>) {
+            fn __drop_inner() {}
+            let _ = __self;
+        }
+        __drop_inner(self);
+    }
+}
+fn main() {}
diff --git a/tests/expand/pinned_drop/enum.rs b/tests/expand/pinned_drop/enum.rs
new file mode 100644 (file)
index 0000000..c162ef6
--- /dev/null
@@ -0,0 +1,23 @@
+use std::pin::Pin;
+
+use pin_project::{pin_project, pinned_drop};
+
+#[pin_project(PinnedDrop, project = EnumProj, project_ref = EnumProjRef)]
+enum Enum<T, U> {
+    Struct {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+
+#[pinned_drop]
+impl<T, U> PinnedDrop for Enum<T, U> {
+    fn drop(self: Pin<&mut Self>) {
+        let _ = self;
+    }
+}
+
+fn main() {}
diff --git a/tests/expand/pinned_drop/struct.expanded.rs b/tests/expand/pinned_drop/struct.expanded.rs
new file mode 100644 (file)
index 0000000..d21440d
--- /dev/null
@@ -0,0 +1,116 @@
+use std::pin::Pin;
+use pin_project::{pin_project, pinned_drop};
+#[pin(__private(PinnedDrop))]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __StructProjection<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    }
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __StructProjectionRef<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin (T)>,
+        unpinned: &'pin (U),
+    }
+    impl<T, U> Struct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __StructProjection<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                __StructProjection {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __StructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_ref();
+                __StructProjectionRef {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned;
+        let _ = &this.unpinned;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Struct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    impl<T, U> _pin_project::__private::Drop for Struct<T, U> {
+        fn drop(&mut self) {
+            unsafe {
+                let __pinned_self = _pin_project::__private::Pin::new_unchecked(self);
+                _pin_project::__private::PinnedDrop::drop(__pinned_self);
+            }
+        }
+    }
+};
+#[doc(hidden)]
+impl<T, U> ::pin_project::__private::PinnedDrop for Struct<T, U> {
+    unsafe fn drop(self: Pin<&mut Self>) {
+        #[allow(clippy::needless_pass_by_value)]
+        fn __drop_inner<T, U>(__self: Pin<&mut Struct<T, U>>) {
+            fn __drop_inner() {}
+            let _ = __self;
+        }
+        __drop_inner(self);
+    }
+}
+fn main() {}
diff --git a/tests/expand/pinned_drop/struct.rs b/tests/expand/pinned_drop/struct.rs
new file mode 100644 (file)
index 0000000..691d3cb
--- /dev/null
@@ -0,0 +1,19 @@
+use std::pin::Pin;
+
+use pin_project::{pin_project, pinned_drop};
+
+#[pin_project(PinnedDrop)]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+
+#[pinned_drop]
+impl<T, U> PinnedDrop for Struct<T, U> {
+    fn drop(self: Pin<&mut Self>) {
+        let _ = self;
+    }
+}
+
+fn main() {}
diff --git a/tests/expand/pinned_drop/tuple_struct.expanded.rs b/tests/expand/pinned_drop/tuple_struct.expanded.rs
new file mode 100644 (file)
index 0000000..9a614ae
--- /dev/null
@@ -0,0 +1,110 @@
+use std::pin::Pin;
+use pin_project::{pin_project, pinned_drop};
+#[pin(__private(PinnedDrop))]
+struct TupleStruct<T, U>(#[pin] T, U);
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __TupleStructProjection<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin mut (T)>,
+        &'pin mut (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __TupleStructProjectionRef<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    impl<T, U> TupleStruct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __TupleStructProjection<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_unchecked_mut();
+                __TupleStructProjection(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __TupleStructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_ref();
+                __TupleStructProjectionRef(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
+        let _ = &this.0;
+        let _ = &this.1;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __TupleStruct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    impl<T, U> _pin_project::__private::Drop for TupleStruct<T, U> {
+        fn drop(&mut self) {
+            unsafe {
+                let __pinned_self = _pin_project::__private::Pin::new_unchecked(self);
+                _pin_project::__private::PinnedDrop::drop(__pinned_self);
+            }
+        }
+    }
+};
+#[doc(hidden)]
+impl<T, U> ::pin_project::__private::PinnedDrop for TupleStruct<T, U> {
+    unsafe fn drop(self: Pin<&mut Self>) {
+        #[allow(clippy::needless_pass_by_value)]
+        fn __drop_inner<T, U>(__self: Pin<&mut TupleStruct<T, U>>) {
+            fn __drop_inner() {}
+            let _ = __self;
+        }
+        __drop_inner(self);
+    }
+}
+fn main() {}
diff --git a/tests/expand/pinned_drop/tuple_struct.rs b/tests/expand/pinned_drop/tuple_struct.rs
new file mode 100644 (file)
index 0000000..1f4917c
--- /dev/null
@@ -0,0 +1,15 @@
+use std::pin::Pin;
+
+use pin_project::{pin_project, pinned_drop};
+
+#[pin_project(PinnedDrop)]
+struct TupleStruct<T, U>(#[pin] T, U);
+
+#[pinned_drop]
+impl<T, U> PinnedDrop for TupleStruct<T, U> {
+    fn drop(self: Pin<&mut Self>) {
+        let _ = self;
+    }
+}
+
+fn main() {}
diff --git a/tests/expand/project_replace/enum.expanded.rs b/tests/expand/project_replace/enum.expanded.rs
new file mode 100644 (file)
index 0000000..178cb99
--- /dev/null
@@ -0,0 +1,119 @@
+use pin_project::pin_project;
+#[pin(__private(project_replace = EnumProjOwn))]
+enum Enum<T, U> {
+    Struct { #[pin] pinned: T, unpinned: U },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(variant_size_differences)]
+#[allow(clippy::large_enum_variant)]
+enum EnumProjOwn<T, U> {
+    Struct { pinned: ::pin_project::__private::PhantomData<T>, unpinned: U },
+    Tuple(::pin_project::__private::PhantomData<T>, U),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    impl<T, U> Enum<T, U> {
+        #[allow(dead_code)]
+        fn project_replace(
+            self: _pin_project::__private::Pin<&mut Self>,
+            __replacement: Self,
+        ) -> EnumProjOwn<T, U> {
+            unsafe {
+                let __self_ptr: *mut Self = self.get_unchecked_mut();
+                let __guard = _pin_project::__private::UnsafeOverwriteGuard::new(
+                    __self_ptr,
+                    __replacement,
+                );
+                match &mut *__self_ptr {
+                    Self::Struct { pinned, unpinned } => {
+                        let __result = EnumProjOwn::Struct {
+                            pinned: _pin_project::__private::PhantomData,
+                            unpinned: _pin_project::__private::ptr::read(unpinned),
+                        };
+                        {
+                            let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                                pinned,
+                            );
+                        }
+                        __result
+                    }
+                    Self::Tuple(_0, _1) => {
+                        let __result = EnumProjOwn::Tuple(
+                            _pin_project::__private::PhantomData,
+                            _pin_project::__private::ptr::read(_1),
+                        );
+                        {
+                            let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                                _0,
+                            );
+                        }
+                        __result
+                    }
+                    Self::Unit => {
+                        let __result = EnumProjOwn::Unit;
+                        {}
+                        __result
+                    }
+                }
+            }
+        }
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Enum<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+        __field1: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait EnumMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> EnumMustNotImplDrop for T {}
+    impl<T, U> EnumMustNotImplDrop for Enum<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Enum<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/project_replace/enum.rs b/tests/expand/project_replace/enum.rs
new file mode 100644 (file)
index 0000000..d737f64
--- /dev/null
@@ -0,0 +1,14 @@
+use pin_project::pin_project;
+
+#[pin_project(project_replace = EnumProjOwn)]
+enum Enum<T, U> {
+    Struct {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+
+fn main() {}
diff --git a/tests/expand/project_replace/struct.expanded.rs b/tests/expand/project_replace/struct.expanded.rs
new file mode 100644 (file)
index 0000000..45839a2
--- /dev/null
@@ -0,0 +1,133 @@
+use pin_project::pin_project;
+#[pin(__private(project_replace))]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __StructProjection<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    }
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __StructProjectionRef<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin (T)>,
+        unpinned: &'pin (U),
+    }
+    #[allow(dead_code)]
+    struct __StructProjectionOwned<T, U> {
+        pinned: ::pin_project::__private::PhantomData<T>,
+        unpinned: U,
+    }
+    impl<T, U> Struct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __StructProjection<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                __StructProjection {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __StructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_ref();
+                __StructProjectionRef {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        fn project_replace(
+            self: _pin_project::__private::Pin<&mut Self>,
+            __replacement: Self,
+        ) -> __StructProjectionOwned<T, U> {
+            unsafe {
+                let __self_ptr: *mut Self = self.get_unchecked_mut();
+                let __guard = _pin_project::__private::UnsafeOverwriteGuard::new(
+                    __self_ptr,
+                    __replacement,
+                );
+                let Self { pinned, unpinned } = &mut *__self_ptr;
+                let __result = __StructProjectionOwned {
+                    pinned: _pin_project::__private::PhantomData,
+                    unpinned: _pin_project::__private::ptr::read(unpinned),
+                };
+                {
+                    let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                        pinned,
+                    );
+                }
+                __result
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned;
+        let _ = &this.unpinned;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __Struct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait StructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> StructMustNotImplDrop for T {}
+    impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Struct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/project_replace/struct.rs b/tests/expand/project_replace/struct.rs
new file mode 100644 (file)
index 0000000..5865526
--- /dev/null
@@ -0,0 +1,10 @@
+use pin_project::pin_project;
+
+#[pin_project(project_replace)]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+
+fn main() {}
diff --git a/tests/expand/project_replace/tuple_struct.expanded.rs b/tests/expand/project_replace/tuple_struct.expanded.rs
new file mode 100644 (file)
index 0000000..cdee3d1
--- /dev/null
@@ -0,0 +1,127 @@
+use pin_project::pin_project;
+#[pin(__private(project_replace))]
+struct TupleStruct<T, U>(#[pin] T, U);
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __TupleStructProjection<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin mut (T)>,
+        &'pin mut (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __TupleStructProjectionRef<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    #[allow(dead_code)]
+    struct __TupleStructProjectionOwned<T, U>(
+        ::pin_project::__private::PhantomData<T>,
+        U,
+    );
+    impl<T, U> TupleStruct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __TupleStructProjection<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_unchecked_mut();
+                __TupleStructProjection(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __TupleStructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_ref();
+                __TupleStructProjectionRef(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+        #[allow(dead_code)]
+        fn project_replace(
+            self: _pin_project::__private::Pin<&mut Self>,
+            __replacement: Self,
+        ) -> __TupleStructProjectionOwned<T, U> {
+            unsafe {
+                let __self_ptr: *mut Self = self.get_unchecked_mut();
+                let __guard = _pin_project::__private::UnsafeOverwriteGuard::new(
+                    __self_ptr,
+                    __replacement,
+                );
+                let Self(_0, _1) = &mut *__self_ptr;
+                let __result = __TupleStructProjectionOwned(
+                    _pin_project::__private::PhantomData,
+                    _pin_project::__private::ptr::read(_1),
+                );
+                {
+                    let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new(
+                        _0,
+                    );
+                }
+                __result
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
+        let _ = &this.0;
+        let _ = &this.1;
+    }
+    #[allow(missing_debug_implementations)]
+    struct __TupleStruct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait TupleStructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> TupleStructMustNotImplDrop for T {}
+    impl<T, U> TupleStructMustNotImplDrop for TupleStruct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for TupleStruct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/project_replace/tuple_struct.rs b/tests/expand/project_replace/tuple_struct.rs
new file mode 100644 (file)
index 0000000..c4d05f5
--- /dev/null
@@ -0,0 +1,6 @@
+use pin_project::pin_project;
+
+#[pin_project(project_replace)]
+struct TupleStruct<T, U>(#[pin] T, U);
+
+fn main() {}
diff --git a/tests/expand/pub/enum.expanded.rs b/tests/expand/pub/enum.expanded.rs
new file mode 100644 (file)
index 0000000..90be268
--- /dev/null
@@ -0,0 +1,145 @@
+use pin_project::pin_project;
+#[pin(__private(project = EnumProj, project_ref = EnumProjRef))]
+pub enum Enum<T, U> {
+    Struct { #[pin] pinned: T, unpinned: U },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+pub(crate) enum EnumProj<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Struct {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    },
+    Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+pub(crate) enum EnumProjRef<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Struct { pinned: ::pin_project::__private::Pin<&'pin (T)>, unpinned: &'pin (U) },
+    Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    impl<T, U> Enum<T, U> {
+        #[allow(dead_code)]
+        pub(crate) fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> EnumProj<'pin, T, U> {
+            unsafe {
+                match self.get_unchecked_mut() {
+                    Self::Struct { pinned, unpinned } => {
+                        EnumProj::Struct {
+                            pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                            unpinned,
+                        }
+                    }
+                    Self::Tuple(_0, _1) => {
+                        EnumProj::Tuple(
+                            _pin_project::__private::Pin::new_unchecked(_0),
+                            _1,
+                        )
+                    }
+                    Self::Unit => EnumProj::Unit,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        pub(crate) fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> EnumProjRef<'pin, T, U> {
+            unsafe {
+                match self.get_ref() {
+                    Self::Struct { pinned, unpinned } => {
+                        EnumProjRef::Struct {
+                            pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                            unpinned,
+                        }
+                    }
+                    Self::Tuple(_0, _1) => {
+                        EnumProjRef::Tuple(
+                            _pin_project::__private::Pin::new_unchecked(_0),
+                            _1,
+                        )
+                    }
+                    Self::Unit => EnumProjRef::Unit,
+                }
+            }
+        }
+    }
+    #[allow(missing_debug_implementations)]
+    pub struct __Enum<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+        __field1: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum<T, U>
+    where
+        __Enum<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait EnumMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> EnumMustNotImplDrop for T {}
+    impl<T, U> EnumMustNotImplDrop for Enum<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Enum<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/pub/enum.rs b/tests/expand/pub/enum.rs
new file mode 100644 (file)
index 0000000..7c8577f
--- /dev/null
@@ -0,0 +1,14 @@
+use pin_project::pin_project;
+
+#[pin_project(project = EnumProj, project_ref = EnumProjRef)]
+pub enum Enum<T, U> {
+    Struct {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+
+fn main() {}
diff --git a/tests/expand/pub/struct.expanded.rs b/tests/expand/pub/struct.expanded.rs
new file mode 100644 (file)
index 0000000..ca31f3d
--- /dev/null
@@ -0,0 +1,104 @@
+use pin_project::pin_project;
+#[pin(__private())]
+pub struct Struct<T, U> {
+    #[pin]
+    pub pinned: T,
+    pub unpinned: U,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    pub(crate) struct __StructProjection<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pub pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        pub unpinned: &'pin mut (U),
+    }
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    pub(crate) struct __StructProjectionRef<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pub pinned: ::pin_project::__private::Pin<&'pin (T)>,
+        pub unpinned: &'pin (U),
+    }
+    impl<T, U> Struct<T, U> {
+        #[allow(dead_code)]
+        pub(crate) fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __StructProjection<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                __StructProjection {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        pub(crate) fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __StructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_ref();
+                __StructProjectionRef {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned;
+        let _ = &this.unpinned;
+    }
+    #[allow(missing_debug_implementations)]
+    pub struct __Struct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct<T, U>
+    where
+        __Struct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait StructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> StructMustNotImplDrop for T {}
+    impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Struct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/pub/struct.rs b/tests/expand/pub/struct.rs
new file mode 100644 (file)
index 0000000..f50d1e9
--- /dev/null
@@ -0,0 +1,10 @@
+use pin_project::pin_project;
+
+#[pin_project]
+pub struct Struct<T, U> {
+    #[pin]
+    pub pinned: T,
+    pub unpinned: U,
+}
+
+fn main() {}
diff --git a/tests/expand/pub/tuple_struct.expanded.rs b/tests/expand/pub/tuple_struct.expanded.rs
new file mode 100644 (file)
index 0000000..5c7efbf
--- /dev/null
@@ -0,0 +1,98 @@
+use pin_project::pin_project;
+#[pin(__private())]
+pub struct TupleStruct<T, U>(#[pin] pub T, pub U);
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    pub(crate) struct __TupleStructProjection<'pin, T, U>(
+        pub ::pin_project::__private::Pin<&'pin mut (T)>,
+        pub &'pin mut (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    pub(crate) struct __TupleStructProjectionRef<'pin, T, U>(
+        pub ::pin_project::__private::Pin<&'pin (T)>,
+        pub &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    impl<T, U> TupleStruct<T, U> {
+        #[allow(dead_code)]
+        pub(crate) fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __TupleStructProjection<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_unchecked_mut();
+                __TupleStructProjection(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        pub(crate) fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __TupleStructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_ref();
+                __TupleStructProjectionRef(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
+        let _ = &this.0;
+        let _ = &this.1;
+    }
+    #[allow(missing_debug_implementations)]
+    pub struct __TupleStruct<'pin, T, U> {
+        __pin_project_use_generics: _pin_project::__private::AlwaysUnpin<
+            'pin,
+            (
+                _pin_project::__private::PhantomData<T>,
+                _pin_project::__private::PhantomData<U>,
+            ),
+        >,
+        __field0: T,
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    #[doc(hidden)]
+    unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct<T, U>
+    where
+        __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin,
+    {}
+    trait TupleStructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> TupleStructMustNotImplDrop for T {}
+    impl<T, U> TupleStructMustNotImplDrop for TupleStruct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for TupleStruct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+fn main() {}
diff --git a/tests/expand/pub/tuple_struct.rs b/tests/expand/pub/tuple_struct.rs
new file mode 100644 (file)
index 0000000..5756aaf
--- /dev/null
@@ -0,0 +1,6 @@
+use pin_project::pin_project;
+
+#[pin_project]
+pub struct TupleStruct<T, U>(#[pin] pub T, pub U);
+
+fn main() {}
diff --git a/tests/expand/unsafe_unpin/enum.expanded.rs b/tests/expand/unsafe_unpin/enum.expanded.rs
new file mode 100644 (file)
index 0000000..1f88ccc
--- /dev/null
@@ -0,0 +1,129 @@
+use pin_project::{pin_project, UnsafeUnpin};
+#[pin(__private(UnsafeUnpin, project = EnumProj, project_ref = EnumProjRef))]
+enum Enum<T, U> {
+    Struct { #[pin] pinned: T, unpinned: U },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+enum EnumProj<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Struct {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    },
+    Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+enum EnumProjRef<'pin, T, U>
+where
+    Enum<T, U>: 'pin,
+{
+    Struct { pinned: ::pin_project::__private::Pin<&'pin (T)>, unpinned: &'pin (U) },
+    Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)),
+    Unit,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    impl<T, U> Enum<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> EnumProj<'pin, T, U> {
+            unsafe {
+                match self.get_unchecked_mut() {
+                    Self::Struct { pinned, unpinned } => {
+                        EnumProj::Struct {
+                            pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                            unpinned,
+                        }
+                    }
+                    Self::Tuple(_0, _1) => {
+                        EnumProj::Tuple(
+                            _pin_project::__private::Pin::new_unchecked(_0),
+                            _1,
+                        )
+                    }
+                    Self::Unit => EnumProj::Unit,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> EnumProjRef<'pin, T, U> {
+            unsafe {
+                match self.get_ref() {
+                    Self::Struct { pinned, unpinned } => {
+                        EnumProjRef::Struct {
+                            pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                            unpinned,
+                        }
+                    }
+                    Self::Tuple(_0, _1) => {
+                        EnumProjRef::Tuple(
+                            _pin_project::__private::Pin::new_unchecked(_0),
+                            _1,
+                        )
+                    }
+                    Self::Unit => EnumProjRef::Unit,
+                }
+            }
+        }
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Enum<T, U>
+    where
+        _pin_project::__private::Wrapper<'pin, Self>: _pin_project::UnsafeUnpin,
+    {}
+    trait EnumMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> EnumMustNotImplDrop for T {}
+    impl<T, U> EnumMustNotImplDrop for Enum<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Enum<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+unsafe impl<T: Unpin, U> UnsafeUnpin for Enum<T, U> {}
+fn main() {}
diff --git a/tests/expand/unsafe_unpin/enum.rs b/tests/expand/unsafe_unpin/enum.rs
new file mode 100644 (file)
index 0000000..d368d71
--- /dev/null
@@ -0,0 +1,16 @@
+use pin_project::{pin_project, UnsafeUnpin};
+
+#[pin_project(UnsafeUnpin, project = EnumProj, project_ref = EnumProjRef)]
+enum Enum<T, U> {
+    Struct {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+
+unsafe impl<T: Unpin, U> UnsafeUnpin for Enum<T, U> {}
+
+fn main() {}
diff --git a/tests/expand/unsafe_unpin/struct.expanded.rs b/tests/expand/unsafe_unpin/struct.expanded.rs
new file mode 100644 (file)
index 0000000..5fa7271
--- /dev/null
@@ -0,0 +1,89 @@
+use pin_project::{pin_project, UnsafeUnpin};
+#[pin(__private(UnsafeUnpin))]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __StructProjection<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin mut (T)>,
+        unpinned: &'pin mut (U),
+    }
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __StructProjectionRef<'pin, T, U>
+    where
+        Struct<T, U>: 'pin,
+    {
+        pinned: ::pin_project::__private::Pin<&'pin (T)>,
+        unpinned: &'pin (U),
+    }
+    impl<T, U> Struct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __StructProjection<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                __StructProjection {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __StructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_ref();
+                __StructProjectionRef {
+                    pinned: _pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &Struct<T, U>) {
+        let _ = &this.pinned;
+        let _ = &this.unpinned;
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for Struct<T, U>
+    where
+        _pin_project::__private::Wrapper<'pin, Self>: _pin_project::UnsafeUnpin,
+    {}
+    trait StructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> StructMustNotImplDrop for T {}
+    impl<T, U> StructMustNotImplDrop for Struct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for Struct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+unsafe impl<T: Unpin, U> UnsafeUnpin for Struct<T, U> {}
+fn main() {}
diff --git a/tests/expand/unsafe_unpin/struct.rs b/tests/expand/unsafe_unpin/struct.rs
new file mode 100644 (file)
index 0000000..b0851b1
--- /dev/null
@@ -0,0 +1,12 @@
+use pin_project::{pin_project, UnsafeUnpin};
+
+#[pin_project(UnsafeUnpin)]
+struct Struct<T, U> {
+    #[pin]
+    pinned: T,
+    unpinned: U,
+}
+
+unsafe impl<T: Unpin, U> UnsafeUnpin for Struct<T, U> {}
+
+fn main() {}
diff --git a/tests/expand/unsafe_unpin/tuple_struct.expanded.rs b/tests/expand/unsafe_unpin/tuple_struct.expanded.rs
new file mode 100644 (file)
index 0000000..de4e926
--- /dev/null
@@ -0,0 +1,83 @@
+use pin_project::{pin_project, UnsafeUnpin};
+#[pin(__private(UnsafeUnpin))]
+struct TupleStruct<T, U>(#[pin] T, U);
+#[allow(box_pointers)]
+#[allow(deprecated)]
+#[allow(explicit_outlives_requirements)]
+#[allow(single_use_lifetimes)]
+#[allow(unreachable_pub)]
+#[allow(unused_tuple_struct_fields)]
+#[allow(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::type_repetition_in_bounds)]
+#[allow(unused_qualifications)]
+#[allow(clippy::semicolon_if_nothing_returned)]
+#[allow(clippy::use_self)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(unused_extern_crates)]
+    extern crate pin_project as _pin_project;
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    struct __TupleStructProjection<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin mut (T)>,
+        &'pin mut (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    struct __TupleStructProjectionRef<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    impl<T, U> TupleStruct<T, U> {
+        #[allow(dead_code)]
+        fn project<'pin>(
+            self: _pin_project::__private::Pin<&'pin mut Self>,
+        ) -> __TupleStructProjection<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_unchecked_mut();
+                __TupleStructProjection(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+        #[allow(dead_code)]
+        #[allow(clippy::missing_const_for_fn)]
+        fn project_ref<'pin>(
+            self: _pin_project::__private::Pin<&'pin Self>,
+        ) -> __TupleStructProjectionRef<'pin, T, U> {
+            unsafe {
+                let Self(_0, _1) = self.get_ref();
+                __TupleStructProjectionRef(
+                    _pin_project::__private::Pin::new_unchecked(_0),
+                    _1,
+                )
+            }
+        }
+    }
+    #[forbid(unaligned_references, safe_packed_borrows)]
+    fn __assert_not_repr_packed<T, U>(this: &TupleStruct<T, U>) {
+        let _ = &this.0;
+        let _ = &this.1;
+    }
+    impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct<T, U>
+    where
+        _pin_project::__private::Wrapper<'pin, Self>: _pin_project::UnsafeUnpin,
+    {}
+    trait TupleStructMustNotImplDrop {}
+    #[allow(clippy::drop_bounds, drop_bounds)]
+    impl<T: _pin_project::__private::Drop> TupleStructMustNotImplDrop for T {}
+    impl<T, U> TupleStructMustNotImplDrop for TupleStruct<T, U> {}
+    #[doc(hidden)]
+    impl<T, U> _pin_project::__private::PinnedDrop for TupleStruct<T, U> {
+        unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {}
+    }
+};
+unsafe impl<T: Unpin, U> UnsafeUnpin for Struct<T, U> {}
+fn main() {}
diff --git a/tests/expand/unsafe_unpin/tuple_struct.rs b/tests/expand/unsafe_unpin/tuple_struct.rs
new file mode 100644 (file)
index 0000000..964617a
--- /dev/null
@@ -0,0 +1,8 @@
+use pin_project::{pin_project, UnsafeUnpin};
+
+#[pin_project(UnsafeUnpin)]
+struct TupleStruct<T, U>(#[pin] T, U);
+
+unsafe impl<T: Unpin, U> UnsafeUnpin for Struct<T, U> {}
+
+fn main() {}
diff --git a/tests/expandtest.rs b/tests/expandtest.rs
new file mode 100644 (file)
index 0000000..4feec1a
--- /dev/null
@@ -0,0 +1,43 @@
+#![cfg(not(miri))]
+#![warn(rust_2018_idioms, single_use_lifetimes)]
+
+use std::{
+    env,
+    process::{Command, ExitStatus, Stdio},
+};
+
+const PATH: &str = "tests/expand/**/*.rs";
+
+#[rustversion::attr(not(nightly), ignore)]
+#[test]
+fn expandtest() {
+    let is_ci = env::var_os("CI").is_some();
+    let cargo = &*env::var("CARGO").unwrap_or_else(|_| "cargo".into());
+    if !has_command(&[cargo, "expand"]) {
+        if is_ci {
+            panic!("expandtest requires cargo-expand");
+        }
+        return;
+    }
+
+    let args = &["--all-features"];
+    if is_ci {
+        macrotest::expand_without_refresh_args(PATH, args);
+    } else {
+        env::set_var("MACROTEST", "overwrite");
+        macrotest::expand_args(PATH, args);
+    }
+}
+
+fn has_command(command: &[&str]) -> bool {
+    Command::new(command[0])
+        .args(&command[1..])
+        .arg("--version")
+        .stdin(Stdio::null())
+        .stdout(Stdio::null())
+        .stderr(Stdio::null())
+        .status()
+        .as_ref()
+        .map(ExitStatus::success)
+        .unwrap_or(false)
+}
diff --git a/tests/include/basic-safe-part.rs b/tests/include/basic-safe-part.rs
new file mode 100644 (file)
index 0000000..0b7c43e
--- /dev/null
@@ -0,0 +1,193 @@
+// default #[pin_project], PinnedDrop, project_replace, !Unpin, and UnsafeUnpin without UnsafeUnpin impl are completely safe.
+
+#[::pin_project::pin_project]
+#[derive(Debug)]
+pub struct DefaultStruct<T, U> {
+    #[pin]
+    pub pinned: T,
+    pub unpinned: U,
+}
+
+#[::pin_project::pin_project(
+    project = DefaultStructNamedProj,
+    project_ref = DefaultStructNamedProjRef,
+)]
+#[derive(Debug)]
+pub struct DefaultStructNamed<T, U> {
+    #[pin]
+    pub pinned: T,
+    pub unpinned: U,
+}
+
+#[::pin_project::pin_project]
+#[derive(Debug)]
+pub struct DefaultTupleStruct<T, U>(#[pin] pub T, pub U);
+
+#[::pin_project::pin_project(
+    project = DefaultTupleStructNamedProj,
+    project_ref = DefaultTupleStructNamedProjRef,
+)]
+#[derive(Debug)]
+pub struct DefaultTupleStructNamed<T, U>(#[pin] pub T, pub U);
+
+#[::pin_project::pin_project(
+    project = DefaultEnumProj,
+    project_ref = DefaultEnumProjRef,
+)]
+#[derive(Debug)]
+pub enum DefaultEnum<T, U> {
+    Struct {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+
+#[::pin_project::pin_project(PinnedDrop)]
+#[derive(Debug)]
+pub struct PinnedDropStruct<T, U> {
+    #[pin]
+    pub pinned: T,
+    pub unpinned: U,
+}
+
+#[::pin_project::pinned_drop]
+impl<T, U> PinnedDrop for PinnedDropStruct<T, U> {
+    fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
+}
+
+#[::pin_project::pin_project(PinnedDrop)]
+#[derive(Debug)]
+pub struct PinnedDropTupleStruct<T, U>(#[pin] pub T, pub U);
+
+#[::pin_project::pinned_drop]
+impl<T, U> PinnedDrop for PinnedDropTupleStruct<T, U> {
+    fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
+}
+
+#[::pin_project::pin_project(
+    PinnedDrop,
+    project = PinnedDropEnumProj,
+    project_ref = PinnedDropEnumProjRef,
+)]
+#[derive(Debug)]
+pub enum PinnedDropEnum<T, U> {
+    Struct {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+
+#[::pin_project::pinned_drop]
+impl<T, U> PinnedDrop for PinnedDropEnum<T, U> {
+    fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
+}
+
+#[::pin_project::pin_project(project_replace)]
+#[derive(Debug)]
+pub struct ReplaceStruct<T, U> {
+    #[pin]
+    pub pinned: T,
+    pub unpinned: U,
+}
+
+#[::pin_project::pin_project(
+    project = ReplaceStructNamedProj,
+    project_ref = ReplaceStructNamedProjRef,
+    project_replace = ReplaceStructNamedProjOwn,
+)]
+#[derive(Debug)]
+pub struct ReplaceStructNamed<T, U> {
+    #[pin]
+    pub pinned: T,
+    pub unpinned: U,
+}
+
+#[::pin_project::pin_project(project_replace)]
+#[derive(Debug)]
+pub struct ReplaceTupleStruct<T, U>(#[pin] pub T, pub U);
+
+#[::pin_project::pin_project(
+    project = ReplaceTupleStructNamedProj,
+    project_ref = ReplaceTupleStructNamedProjRef,
+    project_replace = ReplaceTupleStructNamedProjOwn,
+)]
+#[derive(Debug)]
+pub struct ReplaceTupleStructNamed<T, U>(#[pin] pub T, pub U);
+
+#[::pin_project::pin_project(
+    project = ReplaceEnumProj,
+    project_ref = ReplaceEnumProjRef,
+    project_replace = ReplaceEnumProjOwn,
+)]
+#[derive(Debug)]
+pub enum ReplaceEnum<T, U> {
+    Struct {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+
+#[::pin_project::pin_project(UnsafeUnpin)]
+#[derive(Debug)]
+pub struct UnsafeUnpinStruct<T, U> {
+    #[pin]
+    pub pinned: T,
+    pub unpinned: U,
+}
+
+#[::pin_project::pin_project(UnsafeUnpin)]
+#[derive(Debug)]
+pub struct UnsafeUnpinTupleStruct<T, U>(#[pin] pub T, pub U);
+
+#[::pin_project::pin_project(
+    UnsafeUnpin,
+    project = UnsafeUnpinEnumProj,
+    project_ref = UnsafeUnpinEnumProjRef,
+)]
+#[derive(Debug)]
+pub enum UnsafeUnpinEnum<T, U> {
+    Struct {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    },
+    Tuple(#[pin] T, U),
+    Unit,
+}
+
+#[::pin_project::pin_project(!Unpin)]
+#[derive(Debug)]
+pub struct NotUnpinStruct<T, U> {
+    #[pin]
+    pub pinned: T,
+    pub unpinned: U,
+}
+
+#[::pin_project::pin_project(!Unpin)]
+#[derive(Debug)]
+pub struct NotUnpinTupleStruct<T, U>(#[pin] pub T, pub U);
+
+#[::pin_project::pin_project(
+    !Unpin,
+    project = NotUnpinEnumProj,
+    project_ref = NotUnpinEnumProjRef,
+)]
+#[derive(Debug)]
+pub enum NotUnpinEnum<T, U> {
+    Struct {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    },
+    Tuple(#[pin] T, U),
+    Unit,
+}
diff --git a/tests/include/basic.rs b/tests/include/basic.rs
new file mode 100644 (file)
index 0000000..57cbaeb
--- /dev/null
@@ -0,0 +1,17 @@
+include!("basic-safe-part.rs");
+
+#[allow(clippy::undocumented_unsafe_blocks)]
+unsafe impl<T: ::pin_project::__private::Unpin, U: ::pin_project::__private::Unpin>
+    ::pin_project::UnsafeUnpin for UnsafeUnpinStruct<T, U>
+{
+}
+#[allow(clippy::undocumented_unsafe_blocks)]
+unsafe impl<T: ::pin_project::__private::Unpin, U: ::pin_project::__private::Unpin>
+    ::pin_project::UnsafeUnpin for UnsafeUnpinTupleStruct<T, U>
+{
+}
+#[allow(clippy::undocumented_unsafe_blocks)]
+unsafe impl<T: ::pin_project::__private::Unpin, U: ::pin_project::__private::Unpin>
+    ::pin_project::UnsafeUnpin for UnsafeUnpinEnum<T, U>
+{
+}
diff --git a/tests/lint.rs b/tests/lint.rs
new file mode 100644 (file)
index 0000000..35f05d5
--- /dev/null
@@ -0,0 +1,1190 @@
+// Check interoperability with rustc and clippy lints.
+
+// for old compilers
+#![allow(unknown_lints)]
+#![warn(nonstandard_style, rust_2018_idioms, unused)]
+// Note: This does not guarantee compatibility with forbidding these lints in the future.
+// If rustc adds a new lint, we may not be able to keep this.
+#![forbid(future_incompatible, rust_2018_compatibility, rust_2021_compatibility)]
+// lints forbidden as a part of future_incompatible, rust_2018_compatibility, and rust_2021_compatibility are not included in the list below.
+// elided_lifetimes_in_paths, explicit_outlives_requirements, unused_extern_crates:  as a part of rust_2018_idioms
+// unsafe_op_in_unsafe_fn: requires Rust 1.52. and, we don't generate unsafe fn.
+// non_exhaustive_omitted_patterns: unstable
+// unstable_features: no way to generate #![feature(..)] by macros, expect for unstable inner attribute. and this lint is deprecated: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unstable-features
+// unused_crate_dependencies, must_not_suspend: unrelated
+// unsafe_code: checked in forbid_unsafe module
+#![warn(
+    box_pointers,
+    deprecated_in_future,
+    fuzzy_provenance_casts,
+    lossy_provenance_casts,
+    macro_use_extern_crate,
+    meta_variable_misuse,
+    missing_abi,
+    missing_copy_implementations,
+    missing_debug_implementations,
+    missing_docs,
+    non_ascii_idents,
+    noop_method_call,
+    single_use_lifetimes,
+    trivial_casts,
+    trivial_numeric_casts,
+    unreachable_pub,
+    unused_import_braces,
+    unused_lifetimes,
+    unused_qualifications,
+    unused_results,
+    unused_tuple_struct_fields,
+    variant_size_differences
+)]
+#![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::restriction)]
+#![allow(clippy::blanket_clippy_restriction_lints)] // this is a test, so enable all restriction lints intentionally.
+#![allow(clippy::exhaustive_structs, clippy::exhaustive_enums, clippy::single_char_lifetime_names)] // TODO
+
+pub mod basic {
+    include!("include/basic.rs");
+
+    pub mod inside_macro {
+        #[rustfmt::skip]
+        macro_rules! mac {
+            () => {
+                #[::pin_project::pin_project]
+                #[derive(Debug)]
+                pub struct DefaultStruct<T, U> {
+                    #[pin]
+                    pub pinned: T,
+                    pub unpinned: U,
+                }
+
+                #[::pin_project::pin_project(
+                    project = DefaultStructNamedProj,
+                    project_ref = DefaultStructNamedProjRef,
+                )]
+                #[derive(Debug)]
+                pub struct DefaultStructNamed<T, U> {
+                    #[pin]
+                    pub pinned: T,
+                    pub unpinned: U,
+                }
+
+                #[::pin_project::pin_project]
+                #[derive(Debug)]
+                pub struct DefaultTupleStruct<T, U>(#[pin] pub T, pub U);
+
+                #[::pin_project::pin_project(
+                    project = DefaultTupleStructNamedProj,
+                    project_ref = DefaultTupleStructNamedProjRef,
+                )]
+                #[derive(Debug)]
+                pub struct DefaultTupleStructNamed<T, U>(#[pin] pub T, pub U);
+
+                #[::pin_project::pin_project(
+                    project = DefaultEnumProj,
+                    project_ref = DefaultEnumProjRef,
+                )]
+                #[derive(Debug)]
+                pub enum DefaultEnum<T, U> {
+                    Struct {
+                        #[pin]
+                        pinned: T,
+                        unpinned: U,
+                    },
+                    Tuple(#[pin] T, U),
+                    Unit,
+                }
+
+                #[::pin_project::pin_project(PinnedDrop)]
+                #[derive(Debug)]
+                pub struct PinnedDropStruct<T, U> {
+                    #[pin]
+                    pub pinned: T,
+                    pub unpinned: U,
+                }
+
+                #[::pin_project::pinned_drop]
+                impl<T, U> PinnedDrop for PinnedDropStruct<T, U> {
+                    fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
+                }
+
+                #[::pin_project::pin_project(PinnedDrop)]
+                #[derive(Debug)]
+                pub struct PinnedDropTupleStruct<T, U>(#[pin] pub T, pub U);
+
+                #[::pin_project::pinned_drop]
+                impl<T, U> PinnedDrop for PinnedDropTupleStruct<T, U> {
+                    fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
+                }
+
+                #[::pin_project::pin_project(
+                    PinnedDrop,
+                    project = PinnedDropEnumProj,
+                    project_ref = PinnedDropEnumProjRef,
+                )]
+                #[derive(Debug)]
+                pub enum PinnedDropEnum<T, U> {
+                    Struct {
+                        #[pin]
+                        pinned: T,
+                        unpinned: U,
+                    },
+                    Tuple(#[pin] T, U),
+                    Unit,
+                }
+
+                #[::pin_project::pinned_drop]
+                impl<T, U> PinnedDrop for PinnedDropEnum<T, U> {
+                    fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
+                }
+
+                #[::pin_project::pin_project(project_replace)]
+                #[derive(Debug)]
+                pub struct ReplaceStruct<T, U> {
+                    #[pin]
+                    pub pinned: T,
+                    pub unpinned: U,
+                }
+
+                #[::pin_project::pin_project(
+                    project = ReplaceStructNamedProj,
+                    project_ref = ReplaceStructNamedProjRef,
+                    project_replace = ReplaceStructNamedProjOwn,
+                )]
+                #[derive(Debug)]
+                pub struct ReplaceStructNamed<T, U> {
+                    #[pin]
+                    pub pinned: T,
+                    pub unpinned: U,
+                }
+
+                #[::pin_project::pin_project(project_replace)]
+                #[derive(Debug)]
+                pub struct ReplaceTupleStruct<T, U>(#[pin] pub T, pub U);
+
+                #[::pin_project::pin_project(
+                    project = ReplaceTupleStructNamedProj,
+                    project_ref = ReplaceTupleStructNamedProjRef,
+                    project_replace = ReplaceTupleStructNamedProjOwn,
+                )]
+                #[derive(Debug)]
+                pub struct ReplaceTupleStructNamed<T, U>(#[pin] pub T, pub U);
+
+                #[::pin_project::pin_project(
+                    project = ReplaceEnumProj,
+                    project_ref = ReplaceEnumProjRef,
+                    project_replace = ReplaceEnumProjOwn,
+                )]
+                #[derive(Debug)]
+                pub enum ReplaceEnum<T, U> {
+                    Struct {
+                        #[pin]
+                        pinned: T,
+                        unpinned: U,
+                    },
+                    Tuple(#[pin] T, U),
+                    Unit,
+                }
+
+                #[::pin_project::pin_project(UnsafeUnpin)]
+                #[derive(Debug)]
+                pub struct UnsafeUnpinStruct<T, U> {
+                    #[pin]
+                    pub pinned: T,
+                    pub unpinned: U,
+                }
+
+                #[::pin_project::pin_project(UnsafeUnpin)]
+                #[derive(Debug)]
+                pub struct UnsafeUnpinTupleStruct<T, U>(#[pin] pub T, pub U);
+
+                #[::pin_project::pin_project(
+                    UnsafeUnpin,
+                    project = UnsafeUnpinEnumProj,
+                    project_ref = UnsafeUnpinEnumProjRef,
+                )]
+                #[derive(Debug)]
+                pub enum UnsafeUnpinEnum<T, U> {
+                    Struct {
+                        #[pin]
+                        pinned: T,
+                        unpinned: U,
+                    },
+                    Tuple(#[pin] T, U),
+                    Unit,
+                }
+
+                #[::pin_project::pin_project(!Unpin)]
+                #[derive(Debug)]
+                pub struct NotUnpinStruct<T, U> {
+                    #[pin]
+                    pub pinned: T,
+                    pub unpinned: U,
+                }
+
+                #[::pin_project::pin_project(!Unpin)]
+                #[derive(Debug)]
+                pub struct NotUnpinTupleStruct<T, U>(#[pin] pub T, pub U);
+
+                #[::pin_project::pin_project(
+                    !Unpin,
+                    project = NotUnpinEnumProj,
+                    project_ref = NotUnpinEnumProjRef,
+                )]
+                #[derive(Debug)]
+                pub enum NotUnpinEnum<T, U> {
+                    Struct {
+                        #[pin]
+                        pinned: T,
+                        unpinned: U,
+                    },
+                    Tuple(#[pin] T, U),
+                    Unit,
+                }
+
+                #[allow(clippy::undocumented_unsafe_blocks)]
+                unsafe impl<T: ::pin_project::__private::Unpin, U: ::pin_project::__private::Unpin>
+                    ::pin_project::UnsafeUnpin for UnsafeUnpinStruct<T, U>
+                {
+                }
+                #[allow(clippy::undocumented_unsafe_blocks)]
+                unsafe impl<T: ::pin_project::__private::Unpin, U: ::pin_project::__private::Unpin>
+                    ::pin_project::UnsafeUnpin for UnsafeUnpinTupleStruct<T, U>
+                {
+                }
+                #[allow(clippy::undocumented_unsafe_blocks)]
+                unsafe impl<T: ::pin_project::__private::Unpin, U: ::pin_project::__private::Unpin>
+                    ::pin_project::UnsafeUnpin for UnsafeUnpinEnum<T, U>
+                {
+                }
+            };
+        }
+
+        mac!();
+    }
+}
+
+pub mod forbid_unsafe {
+    #![forbid(unsafe_code)]
+
+    include!("include/basic-safe-part.rs");
+
+    pub mod inside_macro {
+        #[rustfmt::skip]
+        macro_rules! mac {
+            () => {
+                #[::pin_project::pin_project]
+                #[derive(Debug)]
+                pub struct DefaultStruct<T, U> {
+                    #[pin]
+                    pub pinned: T,
+                    pub unpinned: U,
+                }
+
+                #[::pin_project::pin_project(
+                    project = DefaultStructNamedProj,
+                    project_ref = DefaultStructNamedProjRef,
+                )]
+                #[derive(Debug)]
+                pub struct DefaultStructNamed<T, U> {
+                    #[pin]
+                    pub pinned: T,
+                    pub unpinned: U,
+                }
+
+                #[::pin_project::pin_project]
+                #[derive(Debug)]
+                pub struct DefaultTupleStruct<T, U>(#[pin] pub T, pub U);
+
+                #[::pin_project::pin_project(
+                    project = DefaultTupleStructNamedProj,
+                    project_ref = DefaultTupleStructNamedProjRef,
+                )]
+                #[derive(Debug)]
+                pub struct DefaultTupleStructNamed<T, U>(#[pin] pub T, pub U);
+
+                #[::pin_project::pin_project(
+                    project = DefaultEnumProj,
+                    project_ref = DefaultEnumProjRef,
+                )]
+                #[derive(Debug)]
+                pub enum DefaultEnum<T, U> {
+                    Struct {
+                        #[pin]
+                        pinned: T,
+                        unpinned: U,
+                    },
+                    Tuple(#[pin] T, U),
+                    Unit,
+                }
+
+                #[::pin_project::pin_project(PinnedDrop)]
+                #[derive(Debug)]
+                pub struct PinnedDropStruct<T, U> {
+                    #[pin]
+                    pub pinned: T,
+                    pub unpinned: U,
+                }
+
+                #[::pin_project::pinned_drop]
+                impl<T, U> PinnedDrop for PinnedDropStruct<T, U> {
+                    fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
+                }
+
+                #[::pin_project::pin_project(PinnedDrop)]
+                #[derive(Debug)]
+                pub struct PinnedDropTupleStruct<T, U>(#[pin] pub T, pub U);
+
+                #[::pin_project::pinned_drop]
+                impl<T, U> PinnedDrop for PinnedDropTupleStruct<T, U> {
+                    fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
+                }
+
+                #[::pin_project::pin_project(
+                    PinnedDrop,
+                    project = PinnedDropEnumProj,
+                    project_ref = PinnedDropEnumProjRef,
+                )]
+                #[derive(Debug)]
+                pub enum PinnedDropEnum<T, U> {
+                    Struct {
+                        #[pin]
+                        pinned: T,
+                        unpinned: U,
+                    },
+                    Tuple(#[pin] T, U),
+                    Unit,
+                }
+
+                #[::pin_project::pinned_drop]
+                impl<T, U> PinnedDrop for PinnedDropEnum<T, U> {
+                    fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
+                }
+
+                #[::pin_project::pin_project(project_replace)]
+                #[derive(Debug)]
+                pub struct ReplaceStruct<T, U> {
+                    #[pin]
+                    pub pinned: T,
+                    pub unpinned: U,
+                }
+
+                #[::pin_project::pin_project(
+                    project = ReplaceStructNamedProj,
+                    project_ref = ReplaceStructNamedProjRef,
+                    project_replace = ReplaceStructNamedProjOwn,
+                )]
+                #[derive(Debug)]
+                pub struct ReplaceStructNamed<T, U> {
+                    #[pin]
+                    pub pinned: T,
+                    pub unpinned: U,
+                }
+
+                #[::pin_project::pin_project(project_replace)]
+                #[derive(Debug)]
+                pub struct ReplaceTupleStruct<T, U>(#[pin] pub T, pub U);
+
+                #[::pin_project::pin_project(
+                    project = ReplaceTupleStructNamedProj,
+                    project_ref = ReplaceTupleStructNamedProjRef,
+                    project_replace = ReplaceTupleStructNamedProjOwn,
+                )]
+                #[derive(Debug)]
+                pub struct ReplaceTupleStructNamed<T, U>(#[pin] pub T, pub U);
+
+                #[::pin_project::pin_project(
+                    project = ReplaceEnumProj,
+                    project_ref = ReplaceEnumProjRef,
+                    project_replace = ReplaceEnumProjOwn,
+                )]
+                #[derive(Debug)]
+                pub enum ReplaceEnum<T, U> {
+                    Struct {
+                        #[pin]
+                        pinned: T,
+                        unpinned: U,
+                    },
+                    Tuple(#[pin] T, U),
+                    Unit,
+                }
+
+                #[::pin_project::pin_project(UnsafeUnpin)]
+                #[derive(Debug)]
+                pub struct UnsafeUnpinStruct<T, U> {
+                    #[pin]
+                    pub pinned: T,
+                    pub unpinned: U,
+                }
+
+                #[::pin_project::pin_project(UnsafeUnpin)]
+                #[derive(Debug)]
+                pub struct UnsafeUnpinTupleStruct<T, U>(#[pin] pub T, pub U);
+
+                #[::pin_project::pin_project(
+                    UnsafeUnpin,
+                    project = UnsafeUnpinEnumProj,
+                    project_ref = UnsafeUnpinEnumProjRef,
+                )]
+                #[derive(Debug)]
+                pub enum UnsafeUnpinEnum<T, U> {
+                    Struct {
+                        #[pin]
+                        pinned: T,
+                        unpinned: U,
+                    },
+                    Tuple(#[pin] T, U),
+                    Unit,
+                }
+
+                #[::pin_project::pin_project(!Unpin)]
+                #[derive(Debug)]
+                pub struct NotUnpinStruct<T, U> {
+                    #[pin]
+                    pub pinned: T,
+                    pub unpinned: U,
+                }
+
+                #[::pin_project::pin_project(!Unpin)]
+                #[derive(Debug)]
+                pub struct NotUnpinTupleStruct<T, U>(#[pin] pub T, pub U);
+
+                #[::pin_project::pin_project(
+                    !Unpin,
+                    project = NotUnpinEnumProj,
+                    project_ref = NotUnpinEnumProjRef,
+                )]
+                #[derive(Debug)]
+                pub enum NotUnpinEnum<T, U> {
+                    Struct {
+                        #[pin]
+                        pinned: T,
+                        unpinned: U,
+                    },
+                    Tuple(#[pin] T, U),
+                    Unit,
+                }
+            };
+        }
+
+        mac!();
+    }
+}
+
+pub mod box_pointers {
+    use pin_project::pin_project;
+
+    #[allow(box_pointers)] // for the type itself
+    #[pin_project(project_replace)]
+    #[derive(Debug)]
+    pub struct Struct {
+        #[pin]
+        pub p: Box<isize>,
+        pub u: Box<isize>,
+    }
+
+    #[allow(box_pointers)] // for the type itself
+    #[pin_project(project_replace)]
+    #[derive(Debug)]
+    pub struct TupleStruct(#[pin] pub Box<isize>, pub Box<isize>);
+
+    #[allow(box_pointers)] // for the type itself
+    #[pin_project(
+        project = EnumProj,
+        project_ref = EnumProjRef,
+        project_replace = EnumProjOwn,
+    )]
+    #[derive(Debug)]
+    pub enum Enum {
+        Struct {
+            #[pin]
+            p: Box<isize>,
+            u: Box<isize>,
+        },
+        Tuple(#[pin] Box<isize>, Box<isize>),
+        Unit,
+    }
+
+    pub mod inside_macro {
+        use pin_project::pin_project;
+
+        #[rustfmt::skip]
+        macro_rules! mac {
+            () => {
+                #[allow(box_pointers)] // for the type itself
+                #[pin_project(project_replace)]
+                #[derive(Debug)]
+                pub struct Struct {
+                    #[pin]
+                    pub p: Box<isize>,
+                    pub u: Box<isize>,
+                }
+
+                #[allow(box_pointers)] // for the type itself
+                #[pin_project(project_replace)]
+                #[derive(Debug)]
+                pub struct TupleStruct(#[pin] pub Box<isize>, pub Box<isize>);
+
+                #[allow(box_pointers)] // for the type itself
+                #[pin_project(
+                    project = EnumProj,
+                    project_ref = EnumProjRef,
+                    project_replace = EnumProjOwn,
+                )]
+                #[derive(Debug)]
+                pub enum Enum {
+                    Struct {
+                        #[pin]
+                        p: Box<isize>,
+                        u: Box<isize>,
+                    },
+                    Tuple(#[pin] Box<isize>, Box<isize>),
+                    Unit,
+                }
+            };
+        }
+
+        mac!();
+    }
+}
+
+pub mod deprecated {
+    use pin_project::pin_project;
+
+    #[allow(deprecated)] // for the type itself
+    #[pin_project(project_replace)]
+    #[derive(Debug, Clone, Copy)]
+    #[deprecated]
+    pub struct Struct {
+        #[deprecated]
+        #[pin]
+        pub p: (),
+        #[deprecated]
+        pub u: (),
+    }
+
+    #[allow(deprecated)] // for the type itself
+    #[pin_project(project_replace)]
+    #[derive(Debug, Clone, Copy)]
+    #[deprecated]
+    pub struct TupleStruct(
+        #[deprecated]
+        #[pin]
+        pub (),
+        #[deprecated] pub (),
+    );
+
+    #[allow(deprecated)] // for the type itself
+    #[pin_project(
+        project = EnumProj,
+        project_ref = EnumProjRef,
+        project_replace = EnumProjOwn,
+    )]
+    #[derive(Debug, Clone, Copy)]
+    #[deprecated]
+    pub enum Enum {
+        #[deprecated]
+        Struct {
+            #[deprecated]
+            #[pin]
+            p: (),
+            #[deprecated]
+            u: (),
+        },
+        #[deprecated]
+        Tuple(
+            #[deprecated]
+            #[pin]
+            (),
+            #[deprecated] (),
+        ),
+        #[deprecated]
+        Unit,
+    }
+
+    pub mod inside_macro {
+        use pin_project::pin_project;
+
+        #[rustfmt::skip]
+        macro_rules! mac {
+            () => {
+                #[allow(deprecated)] // for the type itself
+                #[pin_project(project_replace)]
+                #[derive(Debug, Clone, Copy)]
+                #[deprecated]
+                pub struct Struct {
+                    #[deprecated]
+                    #[pin]
+                    pub p: (),
+                    #[deprecated]
+                    pub u: (),
+                }
+
+                #[allow(deprecated)] // for the type itself
+                #[pin_project(project_replace)]
+                #[derive(Debug, Clone, Copy)]
+                #[deprecated]
+                pub struct TupleStruct(
+                    #[deprecated]
+                    #[pin]
+                    pub (),
+                    #[deprecated] pub (),
+                );
+
+                #[allow(deprecated)] // for the type itself
+                #[pin_project(
+                    project = EnumProj,
+                    project_ref = EnumProjRef,
+                    project_replace = EnumProjOwn,
+                )]
+                #[derive(Debug, Clone, Copy)]
+                #[deprecated]
+                pub enum Enum {
+                    #[deprecated]
+                    Struct {
+                        #[deprecated]
+                        #[pin]
+                        p: (),
+                        #[deprecated]
+                        u: (),
+                    },
+                    #[deprecated]
+                    Tuple(
+                        #[deprecated]
+                        #[pin]
+                        (),
+                        #[deprecated] (),
+                    ),
+                    #[deprecated]
+                    Unit,
+                }
+            };
+        }
+
+        mac!();
+    }
+}
+
+pub mod explicit_outlives_requirements {
+    use pin_project::pin_project;
+
+    #[allow(explicit_outlives_requirements)] // for the type itself: https://github.com/rust-lang/rust/issues/60993
+    #[pin_project(project_replace)]
+    #[derive(Debug)]
+    pub struct Struct<'a, T, U>
+    where
+        T: ?Sized,
+        U: ?Sized,
+    {
+        #[pin]
+        pub pinned: &'a mut T,
+        pub unpinned: &'a mut U,
+    }
+
+    #[allow(explicit_outlives_requirements)] // for the type itself: https://github.com/rust-lang/rust/issues/60993
+    #[pin_project(project_replace)]
+    #[derive(Debug)]
+    pub struct TupleStruct<'a, T, U>(#[pin] pub &'a mut T, pub &'a mut U)
+    where
+        T: ?Sized,
+        U: ?Sized;
+
+    #[allow(explicit_outlives_requirements)] // for the type itself: https://github.com/rust-lang/rust/issues/60993
+    #[pin_project(
+        project = EnumProj,
+        project_ref = EnumProjRef,
+        project_replace = EnumProjOwn,
+    )]
+    #[derive(Debug)]
+    pub enum Enum<'a, T, U>
+    where
+        T: ?Sized,
+        U: ?Sized,
+    {
+        Struct {
+            #[pin]
+            pinned: &'a mut T,
+            unpinned: &'a mut U,
+        },
+        Tuple(#[pin] &'a mut T, &'a mut U),
+        Unit,
+    }
+
+    pub mod inside_macro {
+        use pin_project::pin_project;
+
+        #[rustfmt::skip]
+        macro_rules! mac {
+            () => {
+                #[allow(explicit_outlives_requirements)] // for the type itself: https://github.com/rust-lang/rust/issues/60993
+                #[pin_project(project_replace)]
+                #[derive(Debug)]
+                pub struct Struct<'a, T, U>
+                where
+                    T: ?Sized,
+                    U: ?Sized,
+                {
+                    #[pin]
+                    pub pinned: &'a mut T,
+                    pub unpinned: &'a mut U,
+                }
+
+                #[allow(explicit_outlives_requirements)] // for the type itself: https://github.com/rust-lang/rust/issues/60993
+                #[pin_project(project_replace)]
+                #[derive(Debug)]
+                pub struct TupleStruct<'a, T, U>(#[pin] pub &'a mut T, pub &'a mut U)
+                where
+                    T: ?Sized,
+                    U: ?Sized;
+
+                #[allow(explicit_outlives_requirements)] // for the type itself: https://github.com/rust-lang/rust/issues/60993
+                #[pin_project(
+                    project = EnumProj,
+                    project_ref = EnumProjRef,
+                    project_replace = EnumProjOwn,
+                )]
+                #[derive(Debug)]
+                pub enum Enum<'a, T, U>
+                where
+                    T: ?Sized,
+                    U: ?Sized,
+                {
+                    Struct {
+                        #[pin]
+                        pinned: &'a mut T,
+                        unpinned: &'a mut U,
+                    },
+                    Tuple(#[pin] &'a mut T, &'a mut U),
+                    Unit,
+                }
+            };
+        }
+
+        mac!();
+    }
+}
+
+#[allow(missing_debug_implementations)]
+pub mod single_use_lifetimes {
+    use pin_project::pin_project;
+
+    #[allow(unused_lifetimes)]
+    pub trait Trait<'a> {}
+
+    #[allow(unused_lifetimes)] // for the type itself
+    #[allow(single_use_lifetimes)] // for the type itself: https://github.com/rust-lang/rust/issues/55058
+    #[pin_project(project_replace)]
+    pub struct Hrtb<'pin___, T>
+    where
+        for<'pin> &'pin T: Unpin,
+        T: for<'pin> Trait<'pin>,
+        for<'pin, 'pin_, 'pin__> &'pin &'pin_ &'pin__ T: Unpin,
+    {
+        #[pin]
+        _f: &'pin___ mut T,
+    }
+
+    pub mod inside_macro {
+        use pin_project::pin_project;
+
+        #[rustfmt::skip]
+        macro_rules! mac {
+            () => {
+                #[allow(unused_lifetimes)]
+                pub trait Trait<'a> {}
+
+                #[allow(unused_lifetimes)] // for the type itself
+                #[allow(single_use_lifetimes)] // for the type itself: https://github.com/rust-lang/rust/issues/55058
+                #[pin_project(project_replace)]
+                pub struct Hrtb<'pin___, T>
+                where
+                    for<'pin> &'pin T: Unpin,
+                    T: for<'pin> Trait<'pin>,
+                    for<'pin, 'pin_, 'pin__> &'pin &'pin_ &'pin__ T: Unpin,
+                {
+                    #[pin]
+                    _f: &'pin___ mut T,
+                }
+            };
+        }
+
+        mac!();
+    }
+}
+
+pub mod variant_size_differences {
+    use pin_project::pin_project;
+
+    #[allow(missing_debug_implementations, missing_copy_implementations)] // https://github.com/rust-lang/rust/pull/74060
+    #[allow(variant_size_differences)] // for the type itself
+    #[allow(clippy::large_enum_variant)] // for the type itself
+    #[pin_project(
+        project = EnumProj,
+        project_ref = EnumProjRef,
+        project_replace = EnumProjOwn,
+    )]
+    pub enum Enum {
+        V1(u8),
+        V2([u8; 1024]),
+    }
+
+    pub mod inside_macro {
+        use pin_project::pin_project;
+
+        #[rustfmt::skip]
+        macro_rules! mac {
+            () => {
+                #[allow(missing_debug_implementations, missing_copy_implementations)] // https://github.com/rust-lang/rust/pull/74060
+                #[allow(variant_size_differences)] // for the type itself
+                #[allow(clippy::large_enum_variant)] // for the type itself
+                #[pin_project(
+                    project = EnumProj,
+                    project_ref = EnumProjRef,
+                    project_replace = EnumProjOwn,
+                )]
+                pub enum Enum {
+                    V1(u8),
+                    V2([u8; 1024]),
+                }
+            };
+        }
+
+        mac!();
+    }
+}
+
+pub mod clippy_mut_mut {
+    use pin_project::pin_project;
+
+    #[pin_project(project_replace)]
+    #[derive(Debug)]
+    pub struct Struct<'a, T, U> {
+        #[pin]
+        pub pinned: &'a mut T,
+        pub unpinned: &'a mut U,
+    }
+
+    #[pin_project(project_replace)]
+    #[derive(Debug)]
+    pub struct TupleStruct<'a, T, U>(#[pin] &'a mut T, &'a mut U);
+
+    #[pin_project(
+        project = EnumProj,
+        project_ref = EnumProjRef,
+        project_replace = EnumProjOwn,
+    )]
+    #[derive(Debug)]
+    pub enum Enum<'a, T, U> {
+        Struct {
+            #[pin]
+            pinned: &'a mut T,
+            unpinned: &'a mut U,
+        },
+        Tuple(#[pin] &'a mut T, &'a mut U),
+        Unit,
+    }
+
+    pub mod inside_macro {
+        use pin_project::pin_project;
+
+        #[rustfmt::skip]
+        macro_rules! mac {
+            () => {
+                #[pin_project(project_replace)]
+                #[derive(Debug)]
+                pub struct Struct<'a, T, U> {
+                    #[pin]
+                    pub pinned: &'a mut T,
+                    pub unpinned: &'a mut U,
+                }
+
+                #[pin_project(project_replace)]
+                #[derive(Debug)]
+                pub struct TupleStruct<'a, T, U>(#[pin] &'a mut T, &'a mut U);
+
+                #[pin_project(
+                    project = EnumProj,
+                    project_ref = EnumProjRef,
+                    project_replace = EnumProjOwn,
+                )]
+                #[derive(Debug)]
+                pub enum Enum<'a, T, U> {
+                    Struct {
+                        #[pin]
+                        pinned: &'a mut T,
+                        unpinned: &'a mut U,
+                    },
+                    Tuple(#[pin] &'a mut T, &'a mut U),
+                    Unit,
+                }
+            };
+        }
+
+        mac!();
+    }
+}
+
+#[allow(missing_debug_implementations)]
+#[allow(unreachable_pub)]
+mod clippy_redundant_pub_crate {
+    use pin_project::pin_project;
+
+    #[pin_project(project_replace)]
+    pub struct Struct<T, U> {
+        #[pin]
+        pub pinned: T,
+        pub unpinned: U,
+    }
+
+    #[pin_project(project_replace)]
+    pub struct TupleStruct<T, U>(#[pin] pub T, pub U);
+
+    #[allow(dead_code)]
+    #[pin_project(
+        project = EnumProj,
+        project_ref = EnumProjRef,
+        project_replace = EnumProjOwn,
+    )]
+    pub enum Enum<T, U> {
+        Struct {
+            #[pin]
+            pinned: T,
+            unpinned: U,
+        },
+        Tuple(#[pin] T, U),
+        Unit,
+    }
+
+    pub mod inside_macro {
+        use pin_project::pin_project;
+
+        #[allow(clippy::redundant_pub_crate)]
+        #[rustfmt::skip]
+        macro_rules! mac {
+            () => {
+                #[pin_project(project_replace)]
+                pub struct Struct<T, U> {
+                    #[pin]
+                    pub pinned: T,
+                    pub unpinned: U,
+                }
+
+                #[pin_project(project_replace)]
+                pub struct TupleStruct<T, U>(#[pin] pub T, pub U);
+
+                #[allow(dead_code)]
+                #[pin_project(
+                    project = EnumProj,
+                    project_ref = EnumProjRef,
+                    project_replace = EnumProjOwn,
+                )]
+                pub enum Enum<T, U> {
+                    Struct {
+                        #[pin]
+                        pinned: T,
+                        unpinned: U,
+                    },
+                    Tuple(#[pin] T, U),
+                    Unit,
+                }
+            };
+        }
+
+        mac!();
+    }
+}
+
+#[allow(missing_debug_implementations)]
+pub mod clippy_type_repetition_in_bounds {
+    use pin_project::pin_project;
+
+    #[pin_project(project_replace)]
+    pub struct Struct<T, U>
+    where
+        Self: Sized,
+    {
+        #[pin]
+        pub pinned: T,
+        pub unpinned: U,
+    }
+
+    #[pin_project(project_replace)]
+    pub struct TupleStruct<T, U>(#[pin] T, U)
+    where
+        Self: Sized;
+
+    #[pin_project(
+        project = EnumProj,
+        project_ref = EnumProjRef,
+        project_replace = EnumProjOwn,
+    )]
+    pub enum Enum<T, U>
+    where
+        Self: Sized,
+    {
+        Struct {
+            #[pin]
+            pinned: T,
+            unpinned: U,
+        },
+        Tuple(#[pin] T, U),
+        Unit,
+    }
+
+    pub mod inside_macro {
+        use pin_project::pin_project;
+
+        #[rustfmt::skip]
+        macro_rules! mac {
+            () => {
+                #[pin_project(project_replace)]
+                pub struct Struct<T, U>
+                where
+                    Self: Sized,
+                {
+                    #[pin]
+                    pub pinned: T,
+                    pub unpinned: U,
+                }
+
+                #[pin_project(project_replace)]
+                pub struct TupleStruct<T, U>(#[pin] T, U)
+                where
+                    Self: Sized;
+
+                #[pin_project(
+                    project = EnumProj,
+                    project_ref = EnumProjRef,
+                    project_replace = EnumProjOwn,
+                )]
+                pub enum Enum<T, U>
+                where
+                    Self: Sized,
+                {
+                    Struct {
+                        #[pin]
+                        pinned: T,
+                        unpinned: U,
+                    },
+                    Tuple(#[pin] T, U),
+                    Unit,
+                }
+            };
+        }
+
+        mac!();
+    }
+}
+
+#[allow(missing_debug_implementations)]
+pub mod clippy_use_self {
+    use pin_project::pin_project;
+
+    pub trait Trait {
+        type Assoc;
+    }
+
+    #[pin_project(project_replace)]
+    pub struct Generics<T: Trait<Assoc = Self>>
+    where
+        Self: Trait<Assoc = Self>,
+    {
+        _f: T,
+    }
+
+    pub mod inside_macro {
+        use pin_project::pin_project;
+
+        use super::Trait;
+
+        #[rustfmt::skip]
+        macro_rules! mac {
+            () => {
+                #[pin_project(project_replace)]
+                pub struct Generics<T: Trait<Assoc = Self>>
+                where
+                    Self: Trait<Assoc = Self>,
+                {
+                    _f: T,
+                }
+            };
+        }
+
+        mac!();
+    }
+}
+
+#[allow(missing_debug_implementations)]
+pub mod clippy_used_underscore_binding {
+    use pin_project::pin_project;
+
+    #[pin_project(project_replace)]
+    pub struct Struct<T, U> {
+        #[pin]
+        pub _pinned: T,
+        pub _unpinned: U,
+    }
+
+    #[pin_project(
+        project = EnumProj,
+        project_ref = EnumProjRef,
+        project_replace = EnumProjOwn,
+    )]
+    pub enum Enum<T, U> {
+        Struct {
+            #[pin]
+            _pinned: T,
+            _unpinned: U,
+        },
+    }
+
+    pub mod inside_macro {
+        use pin_project::pin_project;
+
+        #[rustfmt::skip]
+        macro_rules! mac {
+            () => {
+                #[pin_project(project_replace)]
+                pub struct Struct<T, U> {
+                    #[pin]
+                    pub _pinned: T,
+                    pub _unpinned: U,
+                }
+
+                #[pin_project(
+                    project = EnumProj,
+                    project_ref = EnumProjRef,
+                    project_replace = EnumProjOwn,
+                )]
+                pub enum Enum<T, U> {
+                    Struct {
+                        #[pin]
+                        _pinned: T,
+                        _unpinned: U,
+                    },
+                }
+            };
+        }
+
+        mac!();
+    }
+}
+
+#[allow(missing_debug_implementations)]
+pub mod clippy_ref_option_ref {
+    use pin_project::pin_project;
+
+    #[pin_project]
+    pub struct Struct<'a> {
+        #[pin]
+        pub _pinned: Option<&'a ()>,
+        pub _unpinned: Option<&'a ()>,
+    }
+
+    #[pin_project(project = EnumProj, project_ref = EnumProjRef)]
+    pub enum Enum<'a> {
+        Struct {
+            #[pin]
+            _pinned: Option<&'a ()>,
+            _unpinned: Option<&'a ()>,
+        },
+    }
+}
diff --git a/tests/pin_project.rs b/tests/pin_project.rs
new file mode 100644 (file)
index 0000000..aa08056
--- /dev/null
@@ -0,0 +1,887 @@
+#![warn(rust_2018_idioms, single_use_lifetimes)]
+#![allow(dead_code)]
+
+#[macro_use]
+mod auxiliary;
+
+use std::{
+    marker::{PhantomData, PhantomPinned},
+    panic,
+    pin::Pin,
+};
+
+use pin_project::{pin_project, pinned_drop, UnsafeUnpin};
+
+#[test]
+fn projection() {
+    #[pin_project(
+        project = StructProj,
+        project_ref = StructProjRef,
+        project_replace = StructProjOwn,
+    )]
+    struct Struct<T, U> {
+        #[pin]
+        f1: T,
+        f2: U,
+    }
+
+    let mut s = Struct { f1: 1, f2: 2 };
+    let mut s_orig = Pin::new(&mut s);
+    let s = s_orig.as_mut().project();
+
+    let _: Pin<&mut i32> = s.f1;
+    assert_eq!(*s.f1, 1);
+    let _: &mut i32 = s.f2;
+    assert_eq!(*s.f2, 2);
+
+    assert_eq!(s_orig.as_ref().f1, 1);
+    assert_eq!(s_orig.as_ref().f2, 2);
+
+    let mut s = Struct { f1: 1, f2: 2 };
+    let mut s = Pin::new(&mut s);
+    {
+        let StructProj { f1, f2 } = s.as_mut().project();
+        let _: Pin<&mut i32> = f1;
+        let _: &mut i32 = f2;
+    }
+    {
+        let StructProjRef { f1, f2 } = s.as_ref().project_ref();
+        let _: Pin<&i32> = f1;
+        let _: &i32 = f2;
+    }
+    {
+        let StructProjOwn { f1, f2 } = s.as_mut().project_replace(Struct { f1: 3, f2: 4 });
+        let _: PhantomData<i32> = f1;
+        let _: i32 = f2;
+        assert_eq!(f2, 2);
+        assert_eq!(s.f1, 3);
+        assert_eq!(s.f2, 4);
+    }
+
+    #[pin_project(project_replace)]
+    struct TupleStruct<T, U>(#[pin] T, U);
+
+    let mut s = TupleStruct(1, 2);
+    let s = Pin::new(&mut s).project();
+
+    let _: Pin<&mut i32> = s.0;
+    assert_eq!(*s.0, 1);
+    let _: &mut i32 = s.1;
+    assert_eq!(*s.1, 2);
+
+    #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
+    #[derive(Eq, PartialEq, Debug)]
+    enum Enum<A, B, C, D> {
+        Tuple(#[pin] A, B),
+        Struct {
+            #[pin]
+            f1: C,
+            f2: D,
+        },
+        Unit,
+    }
+
+    let mut e = Enum::Tuple(1, 2);
+    let mut e = Pin::new(&mut e);
+
+    match e.as_mut().project() {
+        EnumProj::Tuple(x, y) => {
+            let x: Pin<&mut i32> = x;
+            assert_eq!(*x, 1);
+            let y: &mut i32 = y;
+            assert_eq!(*y, 2);
+        }
+        EnumProj::Struct { f1, f2 } => {
+            let _: Pin<&mut i32> = f1;
+            let _: &mut i32 = f2;
+            unreachable!();
+        }
+        EnumProj::Unit => unreachable!(),
+    }
+
+    assert_eq!(&*e, &Enum::Tuple(1, 2));
+
+    let mut e = Enum::Struct { f1: 3, f2: 4 };
+    let mut e = Pin::new(&mut e);
+
+    match e.as_mut().project() {
+        EnumProj::Tuple(x, y) => {
+            let _: Pin<&mut i32> = x;
+            let _: &mut i32 = y;
+            unreachable!();
+        }
+        EnumProj::Struct { f1, f2 } => {
+            let _: Pin<&mut i32> = f1;
+            assert_eq!(*f1, 3);
+            let _: &mut i32 = f2;
+            assert_eq!(*f2, 4);
+        }
+        EnumProj::Unit => unreachable!(),
+    }
+
+    if let EnumProj::Struct { f1, f2 } = e.as_mut().project() {
+        let _: Pin<&mut i32> = f1;
+        assert_eq!(*f1, 3);
+        let _: &mut i32 = f2;
+        assert_eq!(*f2, 4);
+    }
+}
+
+#[test]
+fn enum_project_set() {
+    #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
+    #[derive(Eq, PartialEq, Debug)]
+    enum Enum {
+        V1(#[pin] u8),
+        V2(bool),
+    }
+
+    let mut e = Enum::V1(25);
+    let mut e_orig = Pin::new(&mut e);
+    let e_proj = e_orig.as_mut().project();
+
+    match e_proj {
+        EnumProj::V1(val) => {
+            let new_e = Enum::V2(val.as_ref().get_ref() == &25);
+            e_orig.set(new_e);
+        }
+        EnumProj::V2(_) => unreachable!(),
+    }
+
+    assert_eq!(e, Enum::V2(true));
+}
+
+#[test]
+fn where_clause() {
+    #[pin_project]
+    struct Struct<T>
+    where
+        T: Copy,
+    {
+        f: T,
+    }
+
+    #[pin_project]
+    struct TupleStruct<T>(T)
+    where
+        T: Copy;
+
+    #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
+    enum Enum<T>
+    where
+        T: Copy,
+    {
+        V(T),
+    }
+}
+
+#[test]
+fn where_clause_and_associated_type_field() {
+    #[pin_project(project_replace)]
+    struct Struct1<I>
+    where
+        I: Iterator,
+    {
+        #[pin]
+        f1: I,
+        f2: I::Item,
+    }
+
+    #[pin_project(project_replace)]
+    struct Struct2<I, J>
+    where
+        I: Iterator<Item = J>,
+    {
+        #[pin]
+        f1: I,
+        f2: J,
+    }
+
+    #[pin_project(project_replace)]
+    struct Struct3<T>
+    where
+        T: 'static,
+    {
+        f: T,
+    }
+
+    trait Static: 'static {}
+
+    impl<T> Static for Struct3<T> {}
+
+    #[pin_project(project_replace)]
+    struct TupleStruct<I>(#[pin] I, I::Item)
+    where
+        I: Iterator;
+
+    #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
+    enum Enum<I>
+    where
+        I: Iterator,
+    {
+        V1(#[pin] I),
+        V2(I::Item),
+    }
+}
+
+#[test]
+fn derive_copy() {
+    #[pin_project(project_replace)]
+    #[derive(Clone, Copy)]
+    struct Struct<T> {
+        f: T,
+    }
+
+    fn is_copy<T: Copy>() {}
+
+    is_copy::<Struct<u8>>();
+}
+
+#[test]
+fn move_out() {
+    struct NotCopy;
+
+    #[pin_project(project_replace)]
+    struct Struct {
+        f: NotCopy,
+    }
+
+    let x = Struct { f: NotCopy };
+    let _val: NotCopy = x.f;
+
+    #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
+    enum Enum {
+        V(NotCopy),
+    }
+
+    let x = Enum::V(NotCopy);
+    #[allow(clippy::infallible_destructuring_match)]
+    let _val: NotCopy = match x {
+        Enum::V(val) => val,
+    };
+}
+
+#[test]
+fn trait_bounds_on_type_generics() {
+    #[pin_project(project_replace)]
+    pub struct Struct1<'a, T: ?Sized> {
+        f: &'a mut T,
+    }
+
+    #[pin_project(project_replace)]
+    pub struct Struct2<'a, T: ::core::fmt::Debug> {
+        f: &'a mut T,
+    }
+
+    #[pin_project(project_replace)]
+    pub struct Struct3<'a, T: core::fmt::Debug> {
+        f: &'a mut T,
+    }
+
+    #[pin_project(project_replace)]
+    pub struct Struct4<'a, T: core::fmt::Debug + core::fmt::Display> {
+        f: &'a mut T,
+    }
+
+    #[pin_project(project_replace)]
+    pub struct Struct5<'a, T: core::fmt::Debug + ?Sized> {
+        f: &'a mut T,
+    }
+
+    #[pin_project(project_replace)]
+    pub struct Struct6<'a, T: core::fmt::Debug = [u8; 16]> {
+        f: &'a mut T,
+    }
+
+    let _: Struct6<'_> = Struct6 { f: &mut [0_u8; 16] };
+
+    #[pin_project(project_replace)]
+    pub struct Struct7<T: 'static> {
+        f: T,
+    }
+
+    trait Static: 'static {}
+
+    impl<T> Static for Struct7<T> {}
+
+    #[pin_project(project_replace)]
+    pub struct Struct8<'a, 'b: 'a> {
+        f1: &'a u8,
+        f2: &'b u8,
+    }
+
+    #[pin_project(project_replace)]
+    pub struct TupleStruct<'a, T: ?Sized>(&'a mut T);
+
+    #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
+    enum Enum<'a, T: ?Sized> {
+        V(&'a mut T),
+    }
+}
+
+#[test]
+fn overlapping_lifetime_names() {
+    #[pin_project(project_replace)]
+    pub struct Struct1<'pin, T> {
+        #[pin]
+        f: &'pin mut T,
+    }
+
+    #[pin_project(project_replace)]
+    pub struct Struct2<'pin, 'pin_, 'pin__> {
+        #[pin]
+        f: &'pin &'pin_ &'pin__ (),
+    }
+
+    pub trait Trait<'a> {}
+
+    #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
+    #[pin_project(project_replace)]
+    pub struct Hrtb<'pin___, T>
+    where
+        for<'pin> &'pin T: Unpin,
+        T: for<'pin> Trait<'pin>,
+        for<'pin, 'pin_, 'pin__> &'pin &'pin_ &'pin__ T: Unpin,
+    {
+        #[pin]
+        f: &'pin___ mut T,
+    }
+
+    #[pin_project(PinnedDrop)]
+    pub struct PinnedDropStruct<'pin> {
+        #[pin]
+        f: &'pin (),
+    }
+
+    #[pinned_drop]
+    impl PinnedDrop for PinnedDropStruct<'_> {
+        fn drop(self: Pin<&mut Self>) {}
+    }
+
+    #[pin_project(UnsafeUnpin)]
+    pub struct UnsafeUnpinStruct<'pin> {
+        #[pin]
+        f: &'pin (),
+    }
+
+    unsafe impl UnsafeUnpin for UnsafeUnpinStruct<'_> {}
+
+    #[pin_project(!Unpin)]
+    pub struct NotUnpinStruct<'pin> {
+        #[pin]
+        f: &'pin (),
+    }
+}
+
+#[test]
+fn combine() {
+    #[pin_project(PinnedDrop, UnsafeUnpin)]
+    pub struct PinnedDropWithUnsafeUnpin<T> {
+        #[pin]
+        f: T,
+    }
+
+    #[pinned_drop]
+    impl<T> PinnedDrop for PinnedDropWithUnsafeUnpin<T> {
+        fn drop(self: Pin<&mut Self>) {}
+    }
+
+    unsafe impl<T: Unpin> UnsafeUnpin for PinnedDropWithUnsafeUnpin<T> {}
+
+    #[pin_project(PinnedDrop, !Unpin)]
+    pub struct PinnedDropWithNotUnpin<T> {
+        #[pin]
+        f: T,
+    }
+
+    #[pinned_drop]
+    impl<T> PinnedDrop for PinnedDropWithNotUnpin<T> {
+        fn drop(self: Pin<&mut Self>) {}
+    }
+
+    #[pin_project(UnsafeUnpin, project_replace)]
+    pub struct UnsafeUnpinWithReplace<T> {
+        #[pin]
+        f: T,
+    }
+
+    unsafe impl<T: Unpin> UnsafeUnpin for UnsafeUnpinWithReplace<T> {}
+
+    #[pin_project(!Unpin, project_replace)]
+    pub struct NotUnpinWithReplace<T> {
+        #[pin]
+        f: T,
+    }
+}
+
+#[test]
+fn private_type_in_public_type() {
+    #[pin_project(project_replace)]
+    pub struct PublicStruct<T> {
+        #[pin]
+        inner: PrivateStruct<T>,
+    }
+
+    struct PrivateStruct<T>(T);
+}
+
+#[allow(clippy::needless_lifetimes)]
+#[test]
+fn lifetime_project() {
+    #[pin_project(project_replace)]
+    struct Struct1<T, U> {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    }
+
+    #[pin_project(project_replace)]
+    struct Struct2<'a, T, U> {
+        #[pin]
+        pinned: &'a T,
+        unpinned: U,
+    }
+
+    #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
+    enum Enum<T, U> {
+        V {
+            #[pin]
+            pinned: T,
+            unpinned: U,
+        },
+    }
+
+    impl<T, U> Struct1<T, U> {
+        fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a T> {
+            self.project_ref().pinned
+        }
+        fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut T> {
+            self.project().pinned
+        }
+        fn get_pin_ref_elided(self: Pin<&Self>) -> Pin<&T> {
+            self.project_ref().pinned
+        }
+        fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut T> {
+            self.project().pinned
+        }
+    }
+
+    impl<'b, T, U> Struct2<'b, T, U> {
+        fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a &'b T> {
+            self.project_ref().pinned
+        }
+        fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut &'b T> {
+            self.project().pinned
+        }
+        fn get_pin_ref_elided(self: Pin<&Self>) -> Pin<&&'b T> {
+            self.project_ref().pinned
+        }
+        fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut &'b T> {
+            self.project().pinned
+        }
+    }
+
+    impl<T, U> Enum<T, U> {
+        fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a T> {
+            match self.project_ref() {
+                EnumProjRef::V { pinned, .. } => pinned,
+            }
+        }
+        fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut T> {
+            match self.project() {
+                EnumProj::V { pinned, .. } => pinned,
+            }
+        }
+        fn get_pin_ref_elided(self: Pin<&Self>) -> Pin<&T> {
+            match self.project_ref() {
+                EnumProjRef::V { pinned, .. } => pinned,
+            }
+        }
+        fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut T> {
+            match self.project() {
+                EnumProj::V { pinned, .. } => pinned,
+            }
+        }
+    }
+}
+
+mod visibility {
+    use pin_project::pin_project;
+
+    #[pin_project(project_replace)]
+    pub(crate) struct S {
+        pub f: u8,
+    }
+}
+
+#[test]
+fn visibility() {
+    let mut x = visibility::S { f: 0 };
+    let x = Pin::new(&mut x);
+    let y = x.as_ref().project_ref();
+    let _: &u8 = y.f;
+    let y = x.project();
+    let _: &mut u8 = y.f;
+}
+
+#[test]
+fn trivial_bounds() {
+    #[pin_project(project_replace)]
+    pub struct NoGenerics {
+        #[pin]
+        f: PhantomPinned,
+    }
+
+    assert_not_unpin!(NoGenerics);
+}
+
+#[test]
+fn dst() {
+    #[pin_project]
+    struct Struct1<T: ?Sized> {
+        f: T,
+    }
+
+    let mut x = Struct1 { f: 0_u8 };
+    let x: Pin<&mut Struct1<dyn core::fmt::Debug>> = Pin::new(&mut x as _);
+    let _: &mut (dyn core::fmt::Debug) = x.project().f;
+
+    #[pin_project]
+    struct Struct2<T: ?Sized> {
+        #[pin]
+        f: T,
+    }
+
+    let mut x = Struct2 { f: 0_u8 };
+    let x: Pin<&mut Struct2<dyn core::fmt::Debug + Unpin>> = Pin::new(&mut x as _);
+    let _: Pin<&mut (dyn core::fmt::Debug + Unpin)> = x.project().f;
+
+    #[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993
+    #[pin_project]
+    struct Struct3<T>
+    where
+        T: ?Sized,
+    {
+        f: T,
+    }
+
+    #[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993
+    #[pin_project]
+    struct Struct4<T>
+    where
+        T: ?Sized,
+    {
+        #[pin]
+        f: T,
+    }
+
+    #[pin_project(UnsafeUnpin)]
+    struct Struct5<T: ?Sized> {
+        f: T,
+    }
+
+    #[pin_project(UnsafeUnpin)]
+    struct Struct6<T: ?Sized> {
+        #[pin]
+        f: T,
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct Struct7<T: ?Sized> {
+        f: T,
+    }
+
+    #[pinned_drop]
+    impl<T: ?Sized> PinnedDrop for Struct7<T> {
+        fn drop(self: Pin<&mut Self>) {}
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct Struct8<T: ?Sized> {
+        #[pin]
+        f: T,
+    }
+
+    #[pinned_drop]
+    impl<T: ?Sized> PinnedDrop for Struct8<T> {
+        fn drop(self: Pin<&mut Self>) {}
+    }
+
+    #[pin_project(!Unpin)]
+    struct Struct9<T: ?Sized> {
+        f: T,
+    }
+
+    #[pin_project(!Unpin)]
+    struct Struct10<T: ?Sized> {
+        #[pin]
+        f: T,
+    }
+
+    #[pin_project]
+    struct Struct11<'a, T: ?Sized, U: ?Sized> {
+        f1: &'a mut T,
+        f2: U,
+    }
+
+    #[pin_project]
+    struct TupleStruct1<T: ?Sized>(T);
+
+    #[pin_project]
+    struct TupleStruct2<T: ?Sized>(#[pin] T);
+
+    #[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993
+    #[pin_project]
+    struct TupleStruct3<T>(T)
+    where
+        T: ?Sized;
+
+    #[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993
+    #[pin_project]
+    struct TupleStruct4<T>(#[pin] T)
+    where
+        T: ?Sized;
+
+    #[pin_project(UnsafeUnpin)]
+    struct TupleStruct5<T: ?Sized>(T);
+
+    #[pin_project(UnsafeUnpin)]
+    struct TupleStruct6<T: ?Sized>(#[pin] T);
+
+    #[pin_project(PinnedDrop)]
+    struct TupleStruct7<T: ?Sized>(T);
+
+    #[pinned_drop]
+    impl<T: ?Sized> PinnedDrop for TupleStruct7<T> {
+        fn drop(self: Pin<&mut Self>) {}
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct TupleStruct8<T: ?Sized>(#[pin] T);
+
+    #[pinned_drop]
+    impl<T: ?Sized> PinnedDrop for TupleStruct8<T> {
+        fn drop(self: Pin<&mut Self>) {}
+    }
+
+    #[pin_project(!Unpin)]
+    struct TupleStruct9<T: ?Sized>(T);
+
+    #[pin_project(!Unpin)]
+    struct TupleStruct10<T: ?Sized>(#[pin] T);
+
+    #[pin_project]
+    struct TupleStruct11<'a, T: ?Sized, U: ?Sized>(&'a mut T, U);
+}
+
+#[test]
+fn dyn_type() {
+    #[pin_project]
+    struct Struct1 {
+        f: dyn core::fmt::Debug,
+    }
+
+    #[pin_project]
+    struct Struct2 {
+        #[pin]
+        f: dyn core::fmt::Debug,
+    }
+
+    #[pin_project]
+    struct Struct3 {
+        f: dyn core::fmt::Debug + Send,
+    }
+
+    #[pin_project]
+    struct Struct4 {
+        #[pin]
+        f: dyn core::fmt::Debug + Send,
+    }
+
+    #[pin_project]
+    struct TupleStruct1(dyn core::fmt::Debug);
+
+    #[pin_project]
+    struct TupleStruct2(#[pin] dyn core::fmt::Debug);
+
+    #[pin_project]
+    struct TupleStruct3(dyn core::fmt::Debug + Send);
+
+    #[pin_project]
+    struct TupleStruct4(#[pin] dyn core::fmt::Debug + Send);
+}
+
+#[test]
+fn parse_self() {
+    macro_rules! mac {
+        ($($tt:tt)*) => {
+            $($tt)*
+        };
+    }
+
+    pub trait Trait {
+        type Assoc;
+    }
+
+    #[allow(clippy::type_repetition_in_bounds)]
+    #[pin_project(project_replace)]
+    pub struct Generics<T: Trait<Assoc = Self>>
+    where
+        Self: Trait<Assoc = Self>,
+        <Self as Trait>::Assoc: Sized,
+        mac!(Self): Trait<Assoc = mac!(Self)>,
+    {
+        _f: T,
+    }
+
+    impl<T: Trait<Assoc = Self>> Trait for Generics<T> {
+        type Assoc = Self;
+    }
+
+    #[pin_project(project_replace)]
+    pub struct Struct {
+        _f1: Box<Self>,
+        _f2: Box<<Self as Trait>::Assoc>,
+        _f3: Box<mac!(Self)>,
+        _f4: [(); Self::ASSOC],
+        _f5: [(); Self::assoc()],
+        _f6: [(); mac!(Self::assoc())],
+    }
+
+    impl Struct {
+        const ASSOC: usize = 1;
+        const fn assoc() -> usize {
+            0
+        }
+    }
+
+    impl Trait for Struct {
+        type Assoc = Self;
+    }
+
+    #[pin_project(project_replace)]
+    struct Tuple(
+        Box<Self>,
+        Box<<Self as Trait>::Assoc>,
+        Box<mac!(Self)>,
+        [(); Self::ASSOC],
+        [(); Self::assoc()],
+        [(); mac!(Self::assoc())],
+    );
+
+    impl Tuple {
+        const ASSOC: usize = 1;
+        const fn assoc() -> usize {
+            0
+        }
+    }
+
+    impl Trait for Tuple {
+        type Assoc = Self;
+    }
+
+    #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)]
+    enum Enum {
+        Struct {
+            _f1: Box<Self>,
+            _f2: Box<<Self as Trait>::Assoc>,
+            _f3: Box<mac!(Self)>,
+            _f4: [(); Self::ASSOC],
+            _f5: [(); Self::assoc()],
+            _f6: [(); mac!(Self::assoc())],
+        },
+        Tuple(
+            Box<Self>,
+            Box<<Self as Trait>::Assoc>,
+            Box<mac!(Self)>,
+            [(); Self::ASSOC],
+            [(); Self::assoc()],
+            [(); mac!(Self::assoc())],
+        ),
+    }
+
+    impl Enum {
+        const ASSOC: usize = 1;
+        const fn assoc() -> usize {
+            0
+        }
+    }
+
+    impl Trait for Enum {
+        type Assoc = Self;
+    }
+}
+
+#[test]
+fn no_infer_outlives() {
+    trait Trait<X> {
+        type Y;
+    }
+
+    struct Struct1<A>(A);
+
+    impl<X, T> Trait<X> for Struct1<T> {
+        type Y = Option<T>;
+    }
+
+    #[pin_project(project_replace)]
+    struct Struct2<A, B> {
+        _f: <Struct1<A> as Trait<B>>::Y,
+    }
+}
+
+// https://github.com/rust-lang/rust/issues/47949
+// https://github.com/taiki-e/pin-project/pull/194#discussion_r419098111
+#[allow(clippy::many_single_char_names)]
+#[test]
+fn project_replace_panic() {
+    #[pin_project(project_replace)]
+    struct S<T, U> {
+        #[pin]
+        pinned: T,
+        unpinned: U,
+    }
+
+    struct D<'a>(&'a mut bool, bool);
+    impl Drop for D<'_> {
+        fn drop(&mut self) {
+            *self.0 = true;
+            if self.1 {
+                panic!();
+            }
+        }
+    }
+
+    let (mut a, mut b, mut c, mut d) = (false, false, false, false);
+    let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
+        let mut x = S { pinned: D(&mut a, true), unpinned: D(&mut b, false) };
+        let _y = Pin::new(&mut x)
+            .project_replace(S { pinned: D(&mut c, false), unpinned: D(&mut d, false) });
+        // Previous `x.pinned` was dropped and panicked when `project_replace` is
+        // called, so this is unreachable.
+        unreachable!();
+    }));
+    assert!(res.is_err());
+    assert!(a);
+    assert!(b);
+    assert!(c);
+    assert!(d);
+
+    let (mut a, mut b, mut c, mut d) = (false, false, false, false);
+    let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
+        let mut x = S { pinned: D(&mut a, false), unpinned: D(&mut b, true) };
+        {
+            let _y = Pin::new(&mut x)
+                .project_replace(S { pinned: D(&mut c, false), unpinned: D(&mut d, false) });
+            // `_y` (previous `x.unpinned`) live to the end of this scope, so
+            // this is not unreachable.
+            // unreachable!();
+        }
+        unreachable!();
+    }));
+    assert!(res.is_err());
+    assert!(a);
+    assert!(b);
+    assert!(c);
+    assert!(d);
+}
diff --git a/tests/pinned_drop.rs b/tests/pinned_drop.rs
new file mode 100644 (file)
index 0000000..99273c4
--- /dev/null
@@ -0,0 +1,284 @@
+#![warn(rust_2018_idioms, single_use_lifetimes)]
+
+use std::pin::Pin;
+
+use pin_project::{pin_project, pinned_drop};
+
+#[test]
+fn safe_project() {
+    #[pin_project(PinnedDrop)]
+    pub struct Struct<'a> {
+        was_dropped: &'a mut bool,
+        #[pin]
+        field: u8,
+    }
+
+    #[pinned_drop]
+    impl PinnedDrop for Struct<'_> {
+        fn drop(self: Pin<&mut Self>) {
+            **self.project().was_dropped = true;
+        }
+    }
+
+    let mut was_dropped = false;
+    drop(Struct { was_dropped: &mut was_dropped, field: 42 });
+    assert!(was_dropped);
+}
+
+#[test]
+fn self_call() {
+    #[pin_project(PinnedDrop)]
+    pub struct S<T>(T);
+
+    trait Trait {
+        fn self_ref(&self) {}
+        fn self_pin_ref(self: Pin<&Self>) {}
+        fn self_mut(&mut self) {}
+        fn self_pin_mut(self: Pin<&mut Self>) {}
+        fn assoc_fn(_this: Pin<&mut Self>) {}
+    }
+
+    impl<T> Trait for S<T> {}
+
+    #[pinned_drop]
+    impl<T> PinnedDrop for S<T> {
+        fn drop(mut self: Pin<&mut Self>) {
+            self.self_ref();
+            self.as_ref().self_pin_ref();
+            self.self_mut();
+            self.as_mut().self_pin_mut();
+            Self::assoc_fn(self.as_mut());
+            <Self>::assoc_fn(self.as_mut());
+        }
+    }
+}
+
+#[test]
+fn self_ty() {
+    #[pin_project(PinnedDrop)]
+    pub struct Struct {
+        pub f: (),
+    }
+
+    #[pinned_drop]
+    impl PinnedDrop for Struct {
+        #[allow(irrefutable_let_patterns)]
+        #[allow(clippy::match_single_binding)]
+        fn drop(mut self: Pin<&mut Self>) {
+            // expr
+            let _: Self = Self { f: () };
+
+            // pat
+            match *self {
+                Self { f: () } => {}
+            }
+            if let Self { f: () } = *self {}
+            let Self { f: () } = *self;
+        }
+    }
+
+    #[pin_project(PinnedDrop)]
+    pub struct TupleStruct(());
+
+    #[pinned_drop]
+    impl PinnedDrop for TupleStruct {
+        #[allow(irrefutable_let_patterns)]
+        fn drop(mut self: Pin<&mut Self>) {
+            // expr
+            let _: Self = Self(());
+
+            // pat
+            match *self {
+                Self(_) => {}
+            }
+            if let Self(_) = *self {}
+            let Self(_) = *self;
+        }
+    }
+
+    #[pin_project(PinnedDrop, project = EnumProj, project_ref = EnumProjRef)]
+    pub enum Enum {
+        Struct { f: () },
+        Tuple(()),
+        Unit,
+    }
+
+    #[pinned_drop]
+    impl PinnedDrop for Enum {
+        fn drop(mut self: Pin<&mut Self>) {
+            // expr
+            let _: Self = Self::Struct { f: () };
+            let _: Self = Self::Tuple(());
+            let _: Self = Self::Unit;
+
+            // pat
+            match *self {
+                Self::Struct { f: () } => {}
+                Self::Tuple(_) => {}
+                Self::Unit => {}
+            }
+            if let Self::Struct { f: () } = *self {}
+            if let Self::Tuple(_) = *self {}
+            if let Self::Unit = *self {}
+        }
+    }
+}
+
+#[test]
+fn self_inside_macro_containing_fn() {
+    macro_rules! mac {
+        ($($tt:tt)*) => {
+            $($tt)*
+        };
+    }
+
+    #[pin_project(PinnedDrop)]
+    pub struct S(());
+
+    #[pinned_drop]
+    impl PinnedDrop for S {
+        fn drop(self: Pin<&mut Self>) {
+            mac!({
+                impl S {
+                    pub fn _f(self) -> Self {
+                        self
+                    }
+                }
+            });
+        }
+    }
+}
+
+// See also `ui/pinned_drop/self.rs`.
+#[rustversion::since(1.40)] // https://github.com/rust-lang/rust/pull/64690
+#[test]
+fn self_inside_macro_def() {
+    #[pin_project(PinnedDrop)]
+    pub struct S(());
+
+    #[pinned_drop]
+    impl PinnedDrop for S {
+        fn drop(self: Pin<&mut Self>) {
+            macro_rules! mac {
+                () => {{
+                    let _ = self;
+                    let _ = Self(());
+                }};
+            }
+            mac!();
+        }
+    }
+}
+
+#[test]
+fn self_arg_inside_macro_call() {
+    #[pin_project(PinnedDrop)]
+    struct Struct {
+        f: (),
+    }
+
+    #[pinned_drop]
+    impl PinnedDrop for Struct {
+        fn drop(self: Pin<&mut Self>) {
+            let _: Vec<_> = vec![self.f];
+        }
+    }
+}
+
+#[test]
+fn self_ty_inside_macro_call() {
+    macro_rules! mac {
+        ($($tt:tt)*) => {
+            $($tt)*
+        };
+    }
+
+    #[pin_project(PinnedDrop)]
+    pub struct Struct<T: Send>
+    where
+        mac!(Self): Send,
+    {
+        _f: T,
+    }
+
+    impl<T: Send> Struct<T> {
+        const ASSOC1: usize = 1;
+        fn assoc1() {}
+    }
+
+    trait Trait {
+        type Assoc2;
+        const ASSOC2: usize;
+        fn assoc2();
+    }
+
+    impl<T: Send> Trait for Struct<T> {
+        type Assoc2 = u8;
+        const ASSOC2: usize = 2;
+        fn assoc2() {}
+    }
+
+    #[pinned_drop]
+    impl<T: Send> PinnedDrop for Struct<T>
+    where
+        mac!(Self): Send,
+    {
+        #[allow(path_statements)]
+        #[allow(clippy::no_effect)]
+        fn drop(self: Pin<&mut Self>) {
+            // inherent items
+            mac!(Self::ASSOC1;);
+            mac!(<Self>::ASSOC1;);
+            mac!(Self::assoc1(););
+            mac!(<Self>::assoc1(););
+
+            // trait items
+            mac!(let _: <Self as Trait>::Assoc2;);
+            mac!(Self::ASSOC2;);
+            mac!(<Self>::ASSOC2;);
+            mac!(<Self as Trait>::ASSOC2;);
+            mac!(Self::assoc2(););
+            mac!(<Self>::assoc2(););
+            mac!(<Self as Trait>::assoc2(););
+        }
+    }
+}
+
+#[test]
+fn inside_macro() {
+    #[pin_project(PinnedDrop)]
+    struct S(());
+
+    macro_rules! mac {
+        ($expr:expr) => {
+            #[pinned_drop]
+            impl PinnedDrop for S {
+                fn drop(self: Pin<&mut Self>) {
+                    let _ = $expr;
+                }
+            }
+        };
+    }
+
+    mac!(1);
+}
+
+pub mod self_path {
+    use super::*;
+
+    #[pin_project(PinnedDrop)]
+    pub struct S<T: Unpin>(T);
+
+    fn f() {}
+
+    #[pinned_drop]
+    impl<T: Unpin> PinnedDrop for self::S<T> {
+        fn drop(mut self: Pin<&mut Self>) {
+            self::f();
+            let _: self::S<()> = self::S(());
+            let _: self::S<Pin<&mut Self>> = self::S(self.as_mut());
+            let self::S(()) = self::S(());
+            let self::S(&mut Self(_)) = self::S(&mut *self);
+        }
+    }
+}
diff --git a/tests/proper_unpin.rs b/tests/proper_unpin.rs
new file mode 100644 (file)
index 0000000..0ba3ce3
--- /dev/null
@@ -0,0 +1,153 @@
+#![warn(rust_2018_idioms, single_use_lifetimes)]
+#![allow(dead_code)]
+
+#[macro_use]
+mod auxiliary;
+
+pub mod default {
+    use std::marker::PhantomPinned;
+
+    use pin_project::pin_project;
+
+    struct Inner<T> {
+        f: T,
+    }
+
+    assert_unpin!(Inner<()>);
+    assert_not_unpin!(Inner<PhantomPinned>);
+
+    #[pin_project]
+    struct Struct<T, U> {
+        #[pin]
+        f1: Inner<T>,
+        f2: U,
+    }
+
+    assert_unpin!(Struct<(), ()>);
+    assert_unpin!(Struct<(), PhantomPinned>);
+    assert_not_unpin!(Struct<PhantomPinned, ()>);
+    assert_not_unpin!(Struct<PhantomPinned, PhantomPinned>);
+
+    #[pin_project(project = EnumProj, project_ref = EnumProjRef)]
+    enum Enum<T, U> {
+        V1 {
+            #[pin]
+            f1: Inner<T>,
+            f2: U,
+        },
+    }
+
+    assert_unpin!(Enum<(), ()>);
+    assert_unpin!(Enum<(), PhantomPinned>);
+    assert_not_unpin!(Enum<PhantomPinned, ()>);
+    assert_not_unpin!(Enum<PhantomPinned, PhantomPinned>);
+
+    #[pin_project]
+    struct TrivialBounds {
+        #[pin]
+        f: PhantomPinned,
+    }
+
+    assert_not_unpin!(TrivialBounds);
+
+    #[pin_project]
+    struct PinRef<'a, T, U> {
+        #[pin]
+        f1: &'a mut Inner<T>,
+        f2: U,
+    }
+
+    assert_unpin!(PinRef<'_, PhantomPinned, PhantomPinned>);
+}
+
+pub mod cfg {
+    use std::marker::PhantomPinned;
+
+    use pin_project::pin_project;
+
+    #[pin_project]
+    struct Foo<T> {
+        #[cfg(any())]
+        #[pin]
+        f: T,
+        #[cfg(not(any()))]
+        f: T,
+    }
+
+    assert_unpin!(Foo<PhantomPinned>);
+
+    #[pin_project]
+    struct Bar<T> {
+        #[cfg(any())]
+        f: T,
+        #[cfg(not(any()))]
+        #[pin]
+        f: T,
+    }
+
+    assert_unpin!(Bar<()>);
+    assert_not_unpin!(Bar<PhantomPinned>);
+}
+
+pub mod cfg_attr {
+    use std::marker::PhantomPinned;
+
+    use pin_project::pin_project;
+
+    #[cfg_attr(any(), pin_project)]
+    struct Foo<T> {
+        f: T,
+    }
+
+    assert_unpin!(Foo<()>);
+    assert_not_unpin!(Foo<PhantomPinned>);
+
+    #[cfg_attr(not(any()), pin_project)]
+    struct Bar<T> {
+        #[cfg_attr(not(any()), pin)]
+        f: T,
+    }
+
+    assert_unpin!(Bar<()>);
+    assert_not_unpin!(Bar<PhantomPinned>);
+}
+
+// pin_project(!Unpin)
+pub mod not_unpin {
+    use std::marker::PhantomPinned;
+
+    use pin_project::pin_project;
+
+    struct Inner<T> {
+        f: T,
+    }
+
+    #[pin_project(!Unpin)]
+    struct Struct<T, U> {
+        #[pin]
+        inner: Inner<T>,
+        other: U,
+    }
+
+    assert_not_unpin!(Struct<(), ()>);
+    assert_not_unpin!(Struct<(), PhantomPinned>);
+    assert_not_unpin!(Struct<PhantomPinned, ()>);
+    assert_not_unpin!(Struct<PhantomPinned, PhantomPinned>);
+
+    #[pin_project(!Unpin)]
+    struct TrivialBounds {
+        #[pin]
+        f: PhantomPinned,
+    }
+
+    assert_not_unpin!(TrivialBounds);
+
+    #[pin_project(!Unpin)]
+    struct PinRef<'a, T, U> {
+        #[pin]
+        inner: &'a mut Inner<T>,
+        other: U,
+    }
+
+    assert_not_unpin!(PinRef<'_, (), ()>);
+}
diff --git a/tests/repr_packed.rs b/tests/repr_packed.rs
new file mode 100644 (file)
index 0000000..be7cab9
--- /dev/null
@@ -0,0 +1,52 @@
+#![warn(rust_2018_idioms, single_use_lifetimes)]
+// unaligned_references did not exist in older compilers and safe_packed_borrows was removed in the latest compilers.
+// https://github.com/rust-lang/rust/pull/82525
+#![allow(unknown_lints, renamed_and_removed_lints)]
+#![forbid(unaligned_references, safe_packed_borrows)]
+
+use std::cell::Cell;
+
+// Ensure that the compiler doesn't copy the fields
+// of #[repr(packed)] types during drop, if the field has alignment 1
+// (that is, any reference to the field is guaranteed to have proper alignment)
+// We are currently unable to statically prevent the usage of #[pin_project]
+// on #[repr(packed)] types composed entirely of fields of alignment 1.
+// This shouldn't lead to undefined behavior, as long as the compiler doesn't
+// try to move the field anyway during drop.
+//
+// This tests validates that the compiler is doing what we expect.
+#[test]
+fn weird_repr_packed() {
+    // We keep track of the field address during
+    // drop using a thread local, to avoid changing
+    // the layout of our #[repr(packed)] type.
+    thread_local! {
+        static FIELD_ADDR: Cell<usize> = Cell::new(0);
+    }
+
+    #[repr(packed)]
+    struct Struct {
+        field: u8,
+    }
+
+    impl Drop for Struct {
+        fn drop(&mut self) {
+            FIELD_ADDR.with(|f| {
+                f.set(&self.field as *const u8 as usize);
+            });
+        }
+    }
+
+    #[allow(clippy::let_and_return)]
+    let field_addr = {
+        // We let this field drop by going out of scope,
+        // rather than explicitly calling drop(foo).
+        // Calling drop(foo) causes 'foo' to be moved
+        // into the 'drop' function, resulting in a different
+        // address.
+        let x = Struct { field: 27 };
+        let field_addr = &x.field as *const u8 as usize;
+        field_addr
+    };
+    assert_eq!(field_addr, FIELD_ADDR.with(Cell::get));
+}
diff --git a/tests/ui/cfg/cfg_attr-resolve.rs b/tests/ui/cfg/cfg_attr-resolve.rs
new file mode 100644 (file)
index 0000000..e36cc95
--- /dev/null
@@ -0,0 +1,11 @@
+use std::pin::Pin;
+
+#[cfg_attr(any(), pin_project::pin_project)]
+struct Foo<T> {
+    f: T,
+}
+
+fn main() {
+    let mut x = Foo { f: 0_u8 };
+    let _ = Pin::new(&mut x).project(); //~ ERROR E0599
+}
diff --git a/tests/ui/cfg/cfg_attr-resolve.stderr b/tests/ui/cfg/cfg_attr-resolve.stderr
new file mode 100644 (file)
index 0000000..0393c14
--- /dev/null
@@ -0,0 +1,5 @@
+error[E0599]: no method named `project` found for struct `Pin<&mut Foo<u8>>` in the current scope
+  --> tests/ui/cfg/cfg_attr-resolve.rs:10:30
+   |
+10 |     let _ = Pin::new(&mut x).project(); //~ ERROR E0599
+   |                              ^^^^^^^ method not found in `Pin<&mut Foo<u8>>`
diff --git a/tests/ui/cfg/cfg_attr-type-mismatch.rs b/tests/ui/cfg/cfg_attr-type-mismatch.rs
new file mode 100644 (file)
index 0000000..1b9664b
--- /dev/null
@@ -0,0 +1,25 @@
+use std::pin::Pin;
+
+use pin_project::pin_project;
+
+#[cfg_attr(not(any()), pin_project)]
+struct Foo<T> {
+    #[cfg_attr(any(), pin)]
+    f: T,
+}
+
+#[cfg_attr(not(any()), pin_project)]
+struct Bar<T> {
+    #[cfg_attr(not(any()), pin)]
+    f: T,
+}
+
+fn main() {
+    let mut x = Foo { f: 0_u8 };
+    let x = Pin::new(&mut x).project();
+    let _: Pin<&mut u8> = x.f; //~ ERROR E0308
+
+    let mut x = Bar { f: 0_u8 };
+    let x = Pin::new(&mut x).project();
+    let _: &mut u8 = x.f; //~ ERROR E0308
+}
diff --git a/tests/ui/cfg/cfg_attr-type-mismatch.stderr b/tests/ui/cfg/cfg_attr-type-mismatch.stderr
new file mode 100644 (file)
index 0000000..366d9c7
--- /dev/null
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+  --> tests/ui/cfg/cfg_attr-type-mismatch.rs:20:27
+   |
+20 |     let _: Pin<&mut u8> = x.f; //~ ERROR E0308
+   |            ------------   ^^^ expected struct `Pin`, found `&mut u8`
+   |            |
+   |            expected due to this
+   |
+   = note:         expected struct `Pin<&mut u8>`
+           found mutable reference `&mut u8`
+
+error[E0308]: mismatched types
+  --> tests/ui/cfg/cfg_attr-type-mismatch.rs:24:22
+   |
+24 |     let _: &mut u8 = x.f; //~ ERROR E0308
+   |            -------   ^^^
+   |            |         |
+   |            |         expected `&mut u8`, found struct `Pin`
+   |            |         help: consider mutably borrowing here: `&mut x.f`
+   |            expected due to this
+   |
+   = note: expected mutable reference `&mut u8`
+                         found struct `Pin<&mut u8>`
diff --git a/tests/ui/cfg/packed_sneaky-span-issue-1.rs b/tests/ui/cfg/packed_sneaky-span-issue-1.rs
new file mode 100644 (file)
index 0000000..7e19952
--- /dev/null
@@ -0,0 +1,15 @@
+use auxiliary_macro::hidden_repr;
+use pin_project::pin_project;
+
+#[pin_project]
+#[hidden_repr(packed)] //~ ERROR may not be used on #[repr(packed)] types
+struct S {
+    #[cfg(not(any()))]
+    #[pin]
+    f: u32,
+    #[cfg(any())]
+    #[pin]
+    f: u8,
+}
+
+fn main() {}
diff --git a/tests/ui/cfg/packed_sneaky-span-issue-1.stderr b/tests/ui/cfg/packed_sneaky-span-issue-1.stderr
new file mode 100644 (file)
index 0000000..4f3acc3
--- /dev/null
@@ -0,0 +1,5 @@
+error: #[pin_project] attribute may not be used on #[repr(packed)] types
+ --> tests/ui/cfg/packed_sneaky-span-issue-1.rs:5:15
+  |
+5 | #[hidden_repr(packed)] //~ ERROR may not be used on #[repr(packed)] types
+  |               ^^^^^^
diff --git a/tests/ui/cfg/packed_sneaky-span-issue-2.rs b/tests/ui/cfg/packed_sneaky-span-issue-2.rs
new file mode 100644 (file)
index 0000000..fcea76b
--- /dev/null
@@ -0,0 +1,15 @@
+use auxiliary_macro::hidden_repr;
+use pin_project::pin_project;
+
+#[pin_project]
+#[hidden_repr(packed)] //~ ERROR may not be used on #[repr(packed)] types
+struct S {
+    #[cfg(any())]
+    #[pin]
+    f: u32,
+    #[cfg(not(any()))]
+    #[pin]
+    f: u8,
+}
+
+fn main() {}
diff --git a/tests/ui/cfg/packed_sneaky-span-issue-2.stderr b/tests/ui/cfg/packed_sneaky-span-issue-2.stderr
new file mode 100644 (file)
index 0000000..cc2795a
--- /dev/null
@@ -0,0 +1,5 @@
+error: #[pin_project] attribute may not be used on #[repr(packed)] types
+ --> tests/ui/cfg/packed_sneaky-span-issue-2.rs:5:15
+  |
+5 | #[hidden_repr(packed)] //~ ERROR may not be used on #[repr(packed)] types
+  |               ^^^^^^
diff --git a/tests/ui/cfg/packed_sneaky.rs b/tests/ui/cfg/packed_sneaky.rs
new file mode 100644 (file)
index 0000000..0b01dc9
--- /dev/null
@@ -0,0 +1,12 @@
+use auxiliary_macro::hidden_repr_cfg_not_any;
+use pin_project::pin_project;
+
+// `#[hidden_repr_cfg_not_any(packed)]` generates `#[cfg_attr(not(any()), repr(packed))]`.
+#[pin_project]
+#[hidden_repr_cfg_not_any(packed)] //~ ERROR may not be used on #[repr(packed)] types
+struct S {
+    #[pin]
+    f: u32,
+}
+
+fn main() {}
diff --git a/tests/ui/cfg/packed_sneaky.stderr b/tests/ui/cfg/packed_sneaky.stderr
new file mode 100644 (file)
index 0000000..a54c2ec
--- /dev/null
@@ -0,0 +1,5 @@
+error: #[pin_project] attribute may not be used on #[repr(packed)] types
+ --> tests/ui/cfg/packed_sneaky.rs:6:27
+  |
+6 | #[hidden_repr_cfg_not_any(packed)] //~ ERROR may not be used on #[repr(packed)] types
+  |                           ^^^^^^
diff --git a/tests/ui/cfg/unsupported.rs b/tests/ui/cfg/unsupported.rs
new file mode 100644 (file)
index 0000000..b950d4b
--- /dev/null
@@ -0,0 +1,11 @@
+use pin_project::pin_project;
+
+#[pin_project]
+struct S {
+    //~^ ERROR may not be used on structs with zero fields
+    #[cfg(any())]
+    #[pin]
+    f: u8,
+}
+
+fn main() {}
diff --git a/tests/ui/cfg/unsupported.stderr b/tests/ui/cfg/unsupported.stderr
new file mode 100644 (file)
index 0000000..e1c871c
--- /dev/null
@@ -0,0 +1,11 @@
+error: #[pin_project] attribute may not be used on structs with zero fields
+ --> tests/ui/cfg/unsupported.rs:4:10
+  |
+4 |   struct S {
+  |  __________^
+5 | |     //~^ ERROR may not be used on structs with zero fields
+6 | |     #[cfg(any())]
+7 | |     #[pin]
+8 | |     f: u8,
+9 | | }
+  | |_^
diff --git a/tests/ui/not_unpin/conflict-unpin.rs b/tests/ui/not_unpin/conflict-unpin.rs
new file mode 100644 (file)
index 0000000..8985f37
--- /dev/null
@@ -0,0 +1,30 @@
+use pin_project::pin_project;
+
+#[pin_project(!Unpin)] //~ ERROR E0119
+struct Foo<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+impl<T, U> Unpin for Foo<T, U> where T: Unpin {}
+
+#[pin_project(!Unpin)] //~ ERROR E0119
+struct Bar<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+impl<T, U> Unpin for Bar<T, U> {}
+
+#[pin_project(!Unpin)] //~ ERROR E0119
+struct Baz<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+impl<T: Unpin, U: Unpin> Unpin for Baz<T, U> {}
+
+fn main() {}
diff --git a/tests/ui/not_unpin/conflict-unpin.stderr b/tests/ui/not_unpin/conflict-unpin.stderr
new file mode 100644 (file)
index 0000000..d79fbfb
--- /dev/null
@@ -0,0 +1,26 @@
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Foo<_, _>`
+  --> tests/ui/not_unpin/conflict-unpin.rs:3:15
+   |
+3  | #[pin_project(!Unpin)] //~ ERROR E0119
+   |               ^^^^^^ conflicting implementation for `Foo<_, _>`
+...
+10 | impl<T, U> Unpin for Foo<T, U> where T: Unpin {}
+   | ------------------------------ first implementation here
+
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Bar<_, _>`
+  --> tests/ui/not_unpin/conflict-unpin.rs:12:15
+   |
+12 | #[pin_project(!Unpin)] //~ ERROR E0119
+   |               ^^^^^^ conflicting implementation for `Bar<_, _>`
+...
+19 | impl<T, U> Unpin for Bar<T, U> {}
+   | ------------------------------ first implementation here
+
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Baz<_, _>`
+  --> tests/ui/not_unpin/conflict-unpin.rs:21:15
+   |
+21 | #[pin_project(!Unpin)] //~ ERROR E0119
+   |               ^^^^^^ conflicting implementation for `Baz<_, _>`
+...
+28 | impl<T: Unpin, U: Unpin> Unpin for Baz<T, U> {}
+   | -------------------------------------------- first implementation here
diff --git a/tests/ui/not_unpin/impl-unsafe-unpin.rs b/tests/ui/not_unpin/impl-unsafe-unpin.rs
new file mode 100644 (file)
index 0000000..2c078c7
--- /dev/null
@@ -0,0 +1,30 @@
+use pin_project::{pin_project, UnsafeUnpin};
+
+#[pin_project(!Unpin)] //~ ERROR E0119
+struct Foo<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+unsafe impl<T, U> UnsafeUnpin for Foo<T, U> where T: Unpin {}
+
+#[pin_project(!Unpin)] //~ ERROR E0119
+struct Bar<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+unsafe impl<T, U> UnsafeUnpin for Bar<T, U> {}
+
+#[pin_project(!Unpin)] //~ ERROR E0119
+struct Baz<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+unsafe impl<T: Unpin, U: Unpin> UnsafeUnpin for Baz<T, U> {}
+
+fn main() {}
diff --git a/tests/ui/not_unpin/impl-unsafe-unpin.stderr b/tests/ui/not_unpin/impl-unsafe-unpin.stderr
new file mode 100644 (file)
index 0000000..93f225e
--- /dev/null
@@ -0,0 +1,32 @@
+error[E0119]: conflicting implementations of trait `_::_pin_project::UnsafeUnpin` for type `Foo<_, _>`
+  --> tests/ui/not_unpin/impl-unsafe-unpin.rs:3:1
+   |
+3  | #[pin_project(!Unpin)] //~ ERROR E0119
+   | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Foo<_, _>`
+...
+10 | unsafe impl<T, U> UnsafeUnpin for Foo<T, U> where T: Unpin {}
+   | ------------------------------------------- first implementation here
+   |
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0119]: conflicting implementations of trait `_::_pin_project::UnsafeUnpin` for type `Bar<_, _>`
+  --> tests/ui/not_unpin/impl-unsafe-unpin.rs:12:1
+   |
+12 | #[pin_project(!Unpin)] //~ ERROR E0119
+   | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<_, _>`
+...
+19 | unsafe impl<T, U> UnsafeUnpin for Bar<T, U> {}
+   | ------------------------------------------- first implementation here
+   |
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0119]: conflicting implementations of trait `_::_pin_project::UnsafeUnpin` for type `Baz<_, _>`
+  --> tests/ui/not_unpin/impl-unsafe-unpin.rs:21:1
+   |
+21 | #[pin_project(!Unpin)] //~ ERROR E0119
+   | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Baz<_, _>`
+...
+28 | unsafe impl<T: Unpin, U: Unpin> UnsafeUnpin for Baz<T, U> {}
+   | --------------------------------------------------------- first implementation here
+   |
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/pin_project/add-attr-to-struct.rs b/tests/ui/pin_project/add-attr-to-struct.rs
new file mode 100644 (file)
index 0000000..045e796
--- /dev/null
@@ -0,0 +1,20 @@
+use std::marker::PhantomPinned;
+
+use auxiliary_macro::add_pin_attr;
+use pin_project::pin_project;
+
+#[pin_project]
+#[add_pin_attr(struct)] //~ ERROR duplicate #[pin] attribute
+struct Foo {
+    #[pin]
+    f: PhantomPinned,
+}
+
+#[add_pin_attr(struct)] //~ ERROR #[pin] attribute may only be used on fields of structs or variants
+#[pin_project]
+struct Bar {
+    #[pin]
+    f: PhantomPinned,
+}
+
+fn main() {}
diff --git a/tests/ui/pin_project/add-attr-to-struct.stderr b/tests/ui/pin_project/add-attr-to-struct.stderr
new file mode 100644 (file)
index 0000000..6fb88e8
--- /dev/null
@@ -0,0 +1,15 @@
+error: duplicate #[pin] attribute
+ --> tests/ui/pin_project/add-attr-to-struct.rs:7:1
+  |
+7 | #[add_pin_attr(struct)] //~ ERROR duplicate #[pin] attribute
+  | ^^^^^^^^^^^^^^^^^^^^^^^
+  |
+  = note: this error originates in the attribute macro `add_pin_attr` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: #[pin] attribute may only be used on fields of structs or variants
+  --> tests/ui/pin_project/add-attr-to-struct.rs:13:1
+   |
+13 | #[add_pin_attr(struct)] //~ ERROR #[pin] attribute may only be used on fields of structs or variants
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in the attribute macro `add_pin_attr` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/pin_project/add-pinned-field.rs b/tests/ui/pin_project/add-pinned-field.rs
new file mode 100644 (file)
index 0000000..c415f9c
--- /dev/null
@@ -0,0 +1,23 @@
+use auxiliary_macro::add_pinned_field;
+use pin_project::pin_project;
+
+fn is_unpin<T: Unpin>() {}
+
+#[pin_project]
+#[add_pinned_field]
+struct Foo {
+    #[pin]
+    f: u32,
+}
+
+#[add_pinned_field]
+#[pin_project]
+struct Bar {
+    #[pin]
+    f: u32,
+}
+
+fn main() {
+    is_unpin::<Foo>(); //~ ERROR E0277
+    is_unpin::<Bar>(); //~ ERROR E0277
+}
diff --git a/tests/ui/pin_project/add-pinned-field.stderr b/tests/ui/pin_project/add-pinned-field.stderr
new file mode 100644 (file)
index 0000000..d0832cc
--- /dev/null
@@ -0,0 +1,52 @@
+error[E0277]: `PhantomPinned` cannot be unpinned
+  --> tests/ui/pin_project/add-pinned-field.rs:21:5
+   |
+21 |     is_unpin::<Foo>(); //~ ERROR E0277
+   |     ^^^^^^^^^^^^^^^ within `__Foo<'_>`, the trait `Unpin` is not implemented for `PhantomPinned`
+   |
+   = note: consider using `Box::pin`
+note: required because it appears within the type `__Foo<'_>`
+  --> tests/ui/pin_project/add-pinned-field.rs:8:8
+   |
+8  | struct Foo {
+   |        ^^^
+note: required because of the requirements on the impl of `Unpin` for `Foo`
+  --> tests/ui/pin_project/add-pinned-field.rs:6:1
+   |
+6  | #[pin_project]
+   | ^^^^^^^^^^^^^^
+7  | #[add_pinned_field]
+8  | struct Foo {
+   |        ^^^
+note: required by a bound in `is_unpin`
+  --> tests/ui/pin_project/add-pinned-field.rs:4:16
+   |
+4  | fn is_unpin<T: Unpin>() {}
+   |                ^^^^^ required by this bound in `is_unpin`
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: `PhantomPinned` cannot be unpinned
+  --> tests/ui/pin_project/add-pinned-field.rs:22:5
+   |
+22 |     is_unpin::<Bar>(); //~ ERROR E0277
+   |     ^^^^^^^^^^^^^^^ within `__Bar<'_>`, the trait `Unpin` is not implemented for `PhantomPinned`
+   |
+   = note: consider using `Box::pin`
+note: required because it appears within the type `__Bar<'_>`
+  --> tests/ui/pin_project/add-pinned-field.rs:15:8
+   |
+15 | struct Bar {
+   |        ^^^
+note: required because of the requirements on the impl of `Unpin` for `Bar`
+  --> tests/ui/pin_project/add-pinned-field.rs:14:1
+   |
+14 | #[pin_project]
+   | ^^^^^^^^^^^^^^
+15 | struct Bar {
+   |        ^^^
+note: required by a bound in `is_unpin`
+  --> tests/ui/pin_project/add-pinned-field.rs:4:16
+   |
+4  | fn is_unpin<T: Unpin>() {}
+   |                ^^^^^ required by this bound in `is_unpin`
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/pin_project/conflict-drop.rs b/tests/ui/pin_project/conflict-drop.rs
new file mode 100644 (file)
index 0000000..4fdb118
--- /dev/null
@@ -0,0 +1,32 @@
+use std::pin::Pin;
+
+use pin_project::{pin_project, pinned_drop};
+
+#[pin_project] //~ ERROR E0119
+struct Foo<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+impl<T, U> Drop for Foo<T, U> {
+    fn drop(&mut self) {}
+}
+
+#[pin_project(PinnedDrop)] //~ ERROR E0119
+struct Bar<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+#[pinned_drop]
+impl<T, U> PinnedDrop for Bar<T, U> {
+    fn drop(self: Pin<&mut Self>) {}
+}
+
+impl<T, U> Drop for Bar<T, U> {
+    fn drop(&mut self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/pin_project/conflict-drop.stderr b/tests/ui/pin_project/conflict-drop.stderr
new file mode 100644 (file)
index 0000000..4ae628d
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0119]: conflicting implementations of trait `_::FooMustNotImplDrop` for type `Foo<_, _>`
+ --> tests/ui/pin_project/conflict-drop.rs:5:1
+  |
+5 | #[pin_project] //~ ERROR E0119
+  | ^^^^^^^^^^^^^^
+  | |
+  | first implementation here
+  | conflicting implementation for `Foo<_, _>`
+  |
+  = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0119]: conflicting implementations of trait `std::ops::Drop` for type `Bar<_, _>`
+  --> tests/ui/pin_project/conflict-drop.rs:16:15
+   |
+16 | #[pin_project(PinnedDrop)] //~ ERROR E0119
+   |               ^^^^^^^^^^ conflicting implementation for `Bar<_, _>`
+...
+28 | impl<T, U> Drop for Bar<T, U> {
+   | ----------------------------- first implementation here
diff --git a/tests/ui/pin_project/conflict-unpin.rs b/tests/ui/pin_project/conflict-unpin.rs
new file mode 100644 (file)
index 0000000..f58c45e
--- /dev/null
@@ -0,0 +1,37 @@
+use pin_project::pin_project;
+
+// The same implementation.
+
+#[pin_project] //~ ERROR E0119
+struct Foo<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+// conflicting implementations
+impl<T, U> Unpin for Foo<T, U> where T: Unpin {} // Conditional Unpin impl
+
+// The implementation that under different conditions.
+
+#[pin_project] //~ ERROR E0119
+struct Bar<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+// conflicting implementations
+impl<T, U> Unpin for Bar<T, U> {} // Non-conditional Unpin impl
+
+#[pin_project] //~ ERROR E0119
+struct Baz<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+// conflicting implementations
+impl<T: Unpin, U: Unpin> Unpin for Baz<T, U> {} // Conditional Unpin impl
+
+fn main() {}
diff --git a/tests/ui/pin_project/conflict-unpin.stderr b/tests/ui/pin_project/conflict-unpin.stderr
new file mode 100644 (file)
index 0000000..7df5db2
--- /dev/null
@@ -0,0 +1,32 @@
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Foo<_, _>`
+  --> tests/ui/pin_project/conflict-unpin.rs:5:1
+   |
+5  | #[pin_project] //~ ERROR E0119
+   | ^^^^^^^^^^^^^^ conflicting implementation for `Foo<_, _>`
+...
+13 | impl<T, U> Unpin for Foo<T, U> where T: Unpin {} // Conditional Unpin impl
+   | ------------------------------ first implementation here
+   |
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Bar<_, _>`
+  --> tests/ui/pin_project/conflict-unpin.rs:17:1
+   |
+17 | #[pin_project] //~ ERROR E0119
+   | ^^^^^^^^^^^^^^ conflicting implementation for `Bar<_, _>`
+...
+25 | impl<T, U> Unpin for Bar<T, U> {} // Non-conditional Unpin impl
+   | ------------------------------ first implementation here
+   |
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Baz<_, _>`
+  --> tests/ui/pin_project/conflict-unpin.rs:27:1
+   |
+27 | #[pin_project] //~ ERROR E0119
+   | ^^^^^^^^^^^^^^ conflicting implementation for `Baz<_, _>`
+...
+35 | impl<T: Unpin, U: Unpin> Unpin for Baz<T, U> {} // Conditional Unpin impl
+   | -------------------------------------------- first implementation here
+   |
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/pin_project/impl-unsafe-unpin.rs b/tests/ui/pin_project/impl-unsafe-unpin.rs
new file mode 100644 (file)
index 0000000..562c9b6
--- /dev/null
@@ -0,0 +1,30 @@
+use pin_project::{pin_project, UnsafeUnpin};
+
+#[pin_project] //~ ERROR E0119
+struct Foo<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+unsafe impl<T, U> UnsafeUnpin for Foo<T, U> where T: Unpin {}
+
+#[pin_project] //~ ERROR E0119
+struct Bar<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+unsafe impl<T, U> UnsafeUnpin for Bar<T, U> {}
+
+#[pin_project] //~ ERROR E0119
+struct Baz<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+unsafe impl<T: Unpin, U: Unpin> UnsafeUnpin for Baz<T, U> {}
+
+fn main() {}
diff --git a/tests/ui/pin_project/impl-unsafe-unpin.stderr b/tests/ui/pin_project/impl-unsafe-unpin.stderr
new file mode 100644 (file)
index 0000000..9554b9b
--- /dev/null
@@ -0,0 +1,32 @@
+error[E0119]: conflicting implementations of trait `_::_pin_project::UnsafeUnpin` for type `Foo<_, _>`
+  --> tests/ui/pin_project/impl-unsafe-unpin.rs:3:1
+   |
+3  | #[pin_project] //~ ERROR E0119
+   | ^^^^^^^^^^^^^^ conflicting implementation for `Foo<_, _>`
+...
+10 | unsafe impl<T, U> UnsafeUnpin for Foo<T, U> where T: Unpin {}
+   | ------------------------------------------- first implementation here
+   |
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0119]: conflicting implementations of trait `_::_pin_project::UnsafeUnpin` for type `Bar<_, _>`
+  --> tests/ui/pin_project/impl-unsafe-unpin.rs:12:1
+   |
+12 | #[pin_project] //~ ERROR E0119
+   | ^^^^^^^^^^^^^^ conflicting implementation for `Bar<_, _>`
+...
+19 | unsafe impl<T, U> UnsafeUnpin for Bar<T, U> {}
+   | ------------------------------------------- first implementation here
+   |
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0119]: conflicting implementations of trait `_::_pin_project::UnsafeUnpin` for type `Baz<_, _>`
+  --> tests/ui/pin_project/impl-unsafe-unpin.rs:21:1
+   |
+21 | #[pin_project] //~ ERROR E0119
+   | ^^^^^^^^^^^^^^ conflicting implementation for `Baz<_, _>`
+...
+28 | unsafe impl<T: Unpin, U: Unpin> UnsafeUnpin for Baz<T, U> {}
+   | --------------------------------------------------------- first implementation here
+   |
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/pin_project/import_unnamed.rs b/tests/ui/pin_project/import_unnamed.rs
new file mode 100644 (file)
index 0000000..7926e61
--- /dev/null
@@ -0,0 +1,30 @@
+/// Only named projected types can be imported.
+/// See visibility.rs for named projected types.
+
+mod pub_ {
+    use pin_project::pin_project;
+
+    #[pin_project]
+    pub struct Default(());
+
+    #[pin_project(project_replace)]
+    pub struct Replace(());
+}
+#[allow(unused_imports)]
+pub mod use_ {
+    #[rustfmt::skip]
+    use crate::pub_::__DefaultProjection; //~ ERROR E0432
+    #[rustfmt::skip]
+    use crate::pub_::__DefaultProjectionRef; //~ ERROR E0432
+    #[rustfmt::skip]
+    use crate::pub_::__ReplaceProjection; //~ ERROR E0432
+    #[rustfmt::skip]
+    use crate::pub_::__ReplaceProjectionOwned; //~ ERROR E0432
+    #[rustfmt::skip]
+    use crate::pub_::__ReplaceProjectionRef; //~ ERROR E0432
+
+    // Confirm that the visibility of the original type is not changed.
+    pub use crate::pub_::{Default, Replace};
+}
+
+fn main() {}
diff --git a/tests/ui/pin_project/import_unnamed.stderr b/tests/ui/pin_project/import_unnamed.stderr
new file mode 100644 (file)
index 0000000..260a35a
--- /dev/null
@@ -0,0 +1,29 @@
+error[E0432]: unresolved import `crate::pub_::__DefaultProjection`
+  --> tests/ui/pin_project/import_unnamed.rs:16:9
+   |
+16 |     use crate::pub_::__DefaultProjection; //~ ERROR E0432
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `__DefaultProjection` in `pub_`
+
+error[E0432]: unresolved import `crate::pub_::__DefaultProjectionRef`
+  --> tests/ui/pin_project/import_unnamed.rs:18:9
+   |
+18 |     use crate::pub_::__DefaultProjectionRef; //~ ERROR E0432
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `__DefaultProjectionRef` in `pub_`
+
+error[E0432]: unresolved import `crate::pub_::__ReplaceProjection`
+  --> tests/ui/pin_project/import_unnamed.rs:20:9
+   |
+20 |     use crate::pub_::__ReplaceProjection; //~ ERROR E0432
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `__ReplaceProjection` in `pub_`
+
+error[E0432]: unresolved import `crate::pub_::__ReplaceProjectionOwned`
+  --> tests/ui/pin_project/import_unnamed.rs:22:9
+   |
+22 |     use crate::pub_::__ReplaceProjectionOwned; //~ ERROR E0432
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `__ReplaceProjectionOwned` in `pub_`
+
+error[E0432]: unresolved import `crate::pub_::__ReplaceProjectionRef`
+  --> tests/ui/pin_project/import_unnamed.rs:24:9
+   |
+24 |     use crate::pub_::__ReplaceProjectionRef; //~ ERROR E0432
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `__ReplaceProjectionRef` in `pub_`
diff --git a/tests/ui/pin_project/invalid.rs b/tests/ui/pin_project/invalid.rs
new file mode 100644 (file)
index 0000000..d39a1fd
--- /dev/null
@@ -0,0 +1,280 @@
+mod pin_argument {
+    use pin_project::pin_project;
+
+    #[pin_project]
+    struct Struct {
+        #[pin()] //~ ERROR unexpected token
+        f: (),
+    }
+
+    #[pin_project]
+    struct TupleStruct(#[pin(foo)] ()); //~ ERROR unexpected token
+
+    #[pin_project]
+    enum EnumTuple {
+        V(#[pin(foo)] ()), //~ ERROR unexpected token
+    }
+
+    #[pin_project]
+    enum EnumStruct {
+        V {
+            #[pin(foo)] //~ ERROR unexpected token
+            f: (),
+        },
+    }
+}
+
+mod pin_attribute {
+    use pin_project::pin_project;
+
+    #[pin_project]
+    struct DuplicateStruct {
+        #[pin]
+        #[pin] //~ ERROR duplicate #[pin] attribute
+        f: (),
+    }
+
+    #[pin_project]
+    struct DuplicateTupleStruct(
+        #[pin]
+        #[pin]
+        (),
+        //~^^ ERROR duplicate #[pin] attribute
+    );
+
+    #[pin_project]
+    enum DuplicateEnumTuple {
+        V(
+            #[pin]
+            #[pin]
+            (),
+            //~^^ ERROR duplicate #[pin] attribute
+        ),
+    }
+
+    #[pin_project]
+    enum DuplicateEnumStruct {
+        V {
+            #[pin]
+            #[pin] //~ ERROR duplicate #[pin] attribute
+            f: (),
+        },
+    }
+}
+
+mod pin_item {
+    use pin_project::pin_project;
+
+    #[pin_project]
+    #[pin] //~ ERROR may only be used on fields of structs or variants
+    struct Struct {
+        #[pin]
+        f: (),
+    }
+
+    #[pin_project]
+    enum Variant {
+        #[pin] //~ ERROR may only be used on fields of structs or variants
+        V(()),
+    }
+
+    #[pin_project]
+    #[pin] //~ ERROR may only be used on fields of structs or variants
+    enum Enum {
+        V(()),
+    }
+}
+
+mod pin_project_argument {
+    use pin_project::pin_project;
+
+    #[pin_project(Replace)] //~ ERROR `Replace` argument was removed, use `project_replace` argument instead
+    struct RemovedReplace(#[pin] ());
+
+    #[pin_project(UnsafeUnpin,,)] //~ ERROR expected identifier
+    struct Unexpected1(#[pin] ());
+
+    #[pin_project(Foo)] //~ ERROR unexpected argument
+    struct Unexpected2(#[pin] ());
+
+    #[pin_project(,UnsafeUnpin)] //~ ERROR expected identifier
+    struct Unexpected3(#[pin] ());
+
+    #[pin_project()] // Ok
+    struct Unexpected4(#[pin] ());
+
+    #[pin_project(PinnedDrop PinnedDrop)] //~ ERROR expected `,`
+    struct Unexpected5(#[pin] ());
+
+    #[pin_project(PinnedDrop, PinnedDrop)] //~ ERROR duplicate `PinnedDrop` argument
+    struct DuplicatePinnedDrop(#[pin] ());
+
+    #[pin_project(UnsafeUnpin, UnsafeUnpin)] //~ ERROR duplicate `UnsafeUnpin` argument
+    struct DuplicateUnsafeUnpin(#[pin] ());
+
+    #[pin_project(!Unpin, !Unpin)] //~ ERROR duplicate `!Unpin` argument
+    struct DuplicateNotUnpin(#[pin] ());
+
+    #[pin_project(PinnedDrop, UnsafeUnpin, UnsafeUnpin)] //~ ERROR duplicate `UnsafeUnpin` argument
+    struct Duplicate3(#[pin] ());
+
+    #[pin_project(PinnedDrop, UnsafeUnpin, PinnedDrop, UnsafeUnpin)] //~ ERROR duplicate `PinnedDrop` argument
+    struct Duplicate4(#[pin] ());
+
+    #[pin_project(project = A, project = B)] //~ ERROR duplicate `project` argument
+    struct DuplicateProject(#[pin] ());
+
+    #[pin_project(project = A, project_ref = A, project = B)] //~ ERROR duplicate `project` argument
+    struct DuplicateProject2(#[pin] ());
+
+    #[pin_project(project_ref = A, project_ref = B)] //~ ERROR duplicate `project_ref` argument
+    struct DuplicateProjectRef(#[pin] ());
+
+    #[pin_project(project_replace = A, project_replace = B)] //~ ERROR duplicate `project_replace` argument
+    struct DuplicateProjectReplace1(#[pin] ());
+
+    #[pin_project(project_replace, project_replace = B)] //~ ERROR duplicate `project_replace` argument
+    struct DuplicateProjectReplace2(#[pin] ());
+
+    #[pin_project(project_replace = A, project_replace)] //~ ERROR duplicate `project_replace` argument
+    struct DuplicateProjectReplace3(#[pin] ());
+
+    #[pin_project(project_replace = A)] // Ok
+    struct ProjectReplaceWithoutReplace(#[pin] ());
+
+    #[pin_project(PinnedDrop, project_replace)] //~ ERROR arguments `PinnedDrop` and `project_replace` are mutually exclusive
+    struct PinnedDropWithProjectReplace1(#[pin] ());
+
+    #[pin_project(project_replace, UnsafeUnpin, PinnedDrop)] //~ ERROR arguments `PinnedDrop` and `project_replace` are mutually exclusive
+    struct PinnedDropWithProjectReplace2(#[pin] ());
+
+    #[pin_project(UnsafeUnpin, !Unpin)] //~ ERROR arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive
+    struct UnsafeUnpinWithNotUnpin1(#[pin] ());
+
+    #[pin_project(!Unpin, PinnedDrop, UnsafeUnpin)] //~ ERROR arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive
+    struct UnsafeUnpinWithNotUnpin2(#[pin] ());
+
+    #[pin_project(!)] //~ ERROR expected `!Unpin`, found `!`
+    struct NotUnpin1(#[pin] ());
+
+    #[pin_project(Unpin)] //~ ERROR unexpected argument
+    struct NotUnpin2(#[pin] ());
+
+    #[pin_project(project)] //~ ERROR expected `project = <identifier>`, found `project`
+    struct Project1(#[pin] ());
+
+    #[pin_project(project = )] //~ ERROR expected `project = <identifier>`, found `project =`
+    struct Project2(#[pin] ());
+
+    #[pin_project(project = !)] //~ ERROR expected identifier
+    struct Project3(#[pin] ());
+
+    #[pin_project(project_ref)] //~ ERROR expected `project_ref = <identifier>`, found `project_ref`
+    struct ProjectRef1(#[pin] ());
+
+    #[pin_project(project_ref = )] //~ ERROR expected `project_ref = <identifier>`, found `project_ref =`
+    struct ProjectRef2(#[pin] ());
+
+    #[pin_project(project_ref = !)] //~ ERROR expected identifier
+    struct ProjectRef3(#[pin] ());
+
+    #[pin_project(project_replace)] // Ok
+    struct ProjectReplace1(#[pin] ());
+
+    #[pin_project(project_replace = )] //~ ERROR expected `project_replace = <identifier>`, found `project_replace =`
+    struct ProjectReplace2(#[pin] ());
+
+    #[pin_project(project_replace = !)] //~ ERROR expected identifier
+    struct ProjectReplace3(#[pin] ());
+
+    #[pin_project(project_replace)] //~ ERROR `project_replace` argument requires a value when used on enums
+    enum ProjectReplaceEnum {
+        V(#[pin] ()),
+    }
+}
+
+mod pin_project_conflict_naming {
+    use pin_project::pin_project;
+
+    #[pin_project(project = OrigAndProj)] //~ ERROR name `OrigAndProj` is the same as the original type name
+    struct OrigAndProj(#[pin] ());
+
+    #[pin_project(project_ref = OrigAndProjRef)] //~ ERROR name `OrigAndProjRef` is the same as the original type name
+    struct OrigAndProjRef(#[pin] ());
+
+    #[pin_project(project_replace = OrigAndProjOwn)] //~ ERROR name `OrigAndProjOwn` is the same as the original type name
+    struct OrigAndProjOwn(#[pin] ());
+
+    #[pin_project(project = A, project_ref = A)] //~ ERROR name `A` is already specified by `project` argument
+    struct ProjAndProjRef(#[pin] ());
+
+    #[pin_project(project = A, project_replace = A)] //~ ERROR name `A` is already specified by `project` argument
+    struct ProjAndProjOwn(#[pin] ());
+
+    #[pin_project(project_ref = A, project_replace = A)] //~ ERROR name `A` is already specified by `project_ref` argument
+    struct ProjRefAndProjOwn(#[pin] ());
+}
+
+mod pin_project_attribute {
+    use pin_project::pin_project;
+
+    #[pin_project]
+    #[pin_project] //~ ERROR duplicate #[pin_project] attribute
+    struct Duplicate(#[pin] ());
+}
+
+mod pin_project_item {
+    use pin_project::pin_project;
+
+    #[pin_project]
+    struct Struct {} //~ ERROR may not be used on structs with zero fields
+
+    #[pin_project]
+    struct TupleStruct(); //~ ERROR may not be used on structs with zero fields
+
+    #[pin_project]
+    struct UnitStruct; //~ ERROR may not be used on structs with zero fields
+
+    #[pin_project]
+    enum EnumEmpty {} //~ ERROR may not be used on enums without variants
+
+    #[pin_project]
+    enum EnumDiscriminant {
+        V = 2, //~ ERROR may not be used on enums with discriminants
+    }
+
+    #[pin_project]
+    enum EnumZeroFields {
+        Unit, //~ ERROR may not be used on enums with zero fields
+        Tuple(),
+        Struct {},
+    }
+
+    #[pin_project]
+    union Union {
+        //~^ ERROR may only be used on structs or enums
+        f: (),
+    }
+
+    #[pin_project]
+    impl Impl {} //~ ERROR may only be used on structs or enums
+}
+
+// #[repr(packed)] is always detected first, even on unsupported structs.
+mod pin_project_item_packed {
+    use pin_project::pin_project;
+
+    #[pin_project]
+    #[repr(packed)]
+    struct Struct {} //~ ERROR may not be used on #[repr(packed)] types
+
+    #[pin_project]
+    #[repr(packed)]
+    struct TupleStruct(); //~ ERROR may not be used on #[repr(packed)] types
+
+    #[pin_project]
+    #[repr(packed)]
+    struct UnitStruct; //~ ERROR may not be used on #[repr(packed)] types
+}
+
+fn main() {}
diff --git a/tests/ui/pin_project/invalid.stderr b/tests/ui/pin_project/invalid.stderr
new file mode 100644 (file)
index 0000000..c43d363
--- /dev/null
@@ -0,0 +1,364 @@
+error: unexpected token: `()`
+ --> tests/ui/pin_project/invalid.rs:6:14
+  |
+6 |         #[pin()] //~ ERROR unexpected token
+  |              ^^
+
+error: unexpected token: `(foo)`
+  --> tests/ui/pin_project/invalid.rs:11:29
+   |
+11 |     struct TupleStruct(#[pin(foo)] ()); //~ ERROR unexpected token
+   |                             ^^^^^
+
+error: unexpected token: `(foo)`
+  --> tests/ui/pin_project/invalid.rs:15:16
+   |
+15 |         V(#[pin(foo)] ()), //~ ERROR unexpected token
+   |                ^^^^^
+
+error: unexpected token: `(foo)`
+  --> tests/ui/pin_project/invalid.rs:21:18
+   |
+21 |             #[pin(foo)] //~ ERROR unexpected token
+   |                  ^^^^^
+
+error: duplicate #[pin] attribute
+  --> tests/ui/pin_project/invalid.rs:33:9
+   |
+33 |         #[pin] //~ ERROR duplicate #[pin] attribute
+   |         ^^^^^^
+
+error: duplicate #[pin] attribute
+  --> tests/ui/pin_project/invalid.rs:40:9
+   |
+40 |         #[pin]
+   |         ^^^^^^
+
+error: duplicate #[pin] attribute
+  --> tests/ui/pin_project/invalid.rs:49:13
+   |
+49 |             #[pin]
+   |             ^^^^^^
+
+error: duplicate #[pin] attribute
+  --> tests/ui/pin_project/invalid.rs:59:13
+   |
+59 |             #[pin] //~ ERROR duplicate #[pin] attribute
+   |             ^^^^^^
+
+error: #[pin] attribute may only be used on fields of structs or variants
+  --> tests/ui/pin_project/invalid.rs:69:5
+   |
+69 |     #[pin] //~ ERROR may only be used on fields of structs or variants
+   |     ^^^^^^
+
+error: #[pin] attribute may only be used on fields of structs or variants
+  --> tests/ui/pin_project/invalid.rs:77:9
+   |
+77 |         #[pin] //~ ERROR may only be used on fields of structs or variants
+   |         ^^^^^^
+
+error: #[pin] attribute may only be used on fields of structs or variants
+  --> tests/ui/pin_project/invalid.rs:82:5
+   |
+82 |     #[pin] //~ ERROR may only be used on fields of structs or variants
+   |     ^^^^^^
+
+error: `Replace` argument was removed, use `project_replace` argument instead
+  --> tests/ui/pin_project/invalid.rs:91:19
+   |
+91 |     #[pin_project(Replace)] //~ ERROR `Replace` argument was removed, use `project_replace` argument instead
+   |                   ^^^^^^^
+
+error: expected identifier
+  --> tests/ui/pin_project/invalid.rs:94:31
+   |
+94 |     #[pin_project(UnsafeUnpin,,)] //~ ERROR expected identifier
+   |                               ^
+
+error: unexpected argument: Foo
+  --> tests/ui/pin_project/invalid.rs:97:19
+   |
+97 |     #[pin_project(Foo)] //~ ERROR unexpected argument
+   |                   ^^^
+
+error: expected identifier
+   --> tests/ui/pin_project/invalid.rs:100:19
+    |
+100 |     #[pin_project(,UnsafeUnpin)] //~ ERROR expected identifier
+    |                   ^
+
+error: expected `,`
+   --> tests/ui/pin_project/invalid.rs:106:30
+    |
+106 |     #[pin_project(PinnedDrop PinnedDrop)] //~ ERROR expected `,`
+    |                              ^^^^^^^^^^
+
+error: duplicate `PinnedDrop` argument
+   --> tests/ui/pin_project/invalid.rs:109:31
+    |
+109 |     #[pin_project(PinnedDrop, PinnedDrop)] //~ ERROR duplicate `PinnedDrop` argument
+    |                               ^^^^^^^^^^
+
+error: duplicate `UnsafeUnpin` argument
+   --> tests/ui/pin_project/invalid.rs:112:32
+    |
+112 |     #[pin_project(UnsafeUnpin, UnsafeUnpin)] //~ ERROR duplicate `UnsafeUnpin` argument
+    |                                ^^^^^^^^^^^
+
+error: duplicate `!Unpin` argument
+   --> tests/ui/pin_project/invalid.rs:115:27
+    |
+115 |     #[pin_project(!Unpin, !Unpin)] //~ ERROR duplicate `!Unpin` argument
+    |                           ^^^^^^
+
+error: duplicate `UnsafeUnpin` argument
+   --> tests/ui/pin_project/invalid.rs:118:44
+    |
+118 |     #[pin_project(PinnedDrop, UnsafeUnpin, UnsafeUnpin)] //~ ERROR duplicate `UnsafeUnpin` argument
+    |                                            ^^^^^^^^^^^
+
+error: duplicate `PinnedDrop` argument
+   --> tests/ui/pin_project/invalid.rs:121:44
+    |
+121 |     #[pin_project(PinnedDrop, UnsafeUnpin, PinnedDrop, UnsafeUnpin)] //~ ERROR duplicate `PinnedDrop` argument
+    |                                            ^^^^^^^^^^
+
+error: duplicate `project` argument
+   --> tests/ui/pin_project/invalid.rs:124:32
+    |
+124 |     #[pin_project(project = A, project = B)] //~ ERROR duplicate `project` argument
+    |                                ^^^^^^^^^^^
+
+error: duplicate `project` argument
+   --> tests/ui/pin_project/invalid.rs:127:49
+    |
+127 |     #[pin_project(project = A, project_ref = A, project = B)] //~ ERROR duplicate `project` argument
+    |                                                 ^^^^^^^^^^^
+
+error: duplicate `project_ref` argument
+   --> tests/ui/pin_project/invalid.rs:130:36
+    |
+130 |     #[pin_project(project_ref = A, project_ref = B)] //~ ERROR duplicate `project_ref` argument
+    |                                    ^^^^^^^^^^^^^^^
+
+error: duplicate `project_replace` argument
+   --> tests/ui/pin_project/invalid.rs:133:40
+    |
+133 |     #[pin_project(project_replace = A, project_replace = B)] //~ ERROR duplicate `project_replace` argument
+    |                                        ^^^^^^^^^^^^^^^^^^^
+
+error: duplicate `project_replace` argument
+   --> tests/ui/pin_project/invalid.rs:136:36
+    |
+136 |     #[pin_project(project_replace, project_replace = B)] //~ ERROR duplicate `project_replace` argument
+    |                                    ^^^^^^^^^^^^^^^^^^^
+
+error: duplicate `project_replace` argument
+   --> tests/ui/pin_project/invalid.rs:139:40
+    |
+139 |     #[pin_project(project_replace = A, project_replace)] //~ ERROR duplicate `project_replace` argument
+    |                                        ^^^^^^^^^^^^^^^
+
+error: arguments `PinnedDrop` and `project_replace` are mutually exclusive
+   --> tests/ui/pin_project/invalid.rs:145:19
+    |
+145 |     #[pin_project(PinnedDrop, project_replace)] //~ ERROR arguments `PinnedDrop` and `project_replace` are mutually exclusive
+    |                   ^^^^^^^^^^
+
+error: arguments `PinnedDrop` and `project_replace` are mutually exclusive
+   --> tests/ui/pin_project/invalid.rs:148:49
+    |
+148 |     #[pin_project(project_replace, UnsafeUnpin, PinnedDrop)] //~ ERROR arguments `PinnedDrop` and `project_replace` are mutually exclusive
+    |                                                 ^^^^^^^^^^
+
+error: arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive
+   --> tests/ui/pin_project/invalid.rs:151:19
+    |
+151 |     #[pin_project(UnsafeUnpin, !Unpin)] //~ ERROR arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive
+    |                   ^^^^^^^^^^^
+
+error: arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive
+   --> tests/ui/pin_project/invalid.rs:154:39
+    |
+154 |     #[pin_project(!Unpin, PinnedDrop, UnsafeUnpin)] //~ ERROR arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive
+    |                                       ^^^^^^^^^^^
+
+error: expected `!Unpin`, found `!`
+   --> tests/ui/pin_project/invalid.rs:157:19
+    |
+157 |     #[pin_project(!)] //~ ERROR expected `!Unpin`, found `!`
+    |                   ^
+
+error: unexpected argument: Unpin
+   --> tests/ui/pin_project/invalid.rs:160:19
+    |
+160 |     #[pin_project(Unpin)] //~ ERROR unexpected argument
+    |                   ^^^^^
+
+error: expected `project = <identifier>`, found `project`
+   --> tests/ui/pin_project/invalid.rs:163:19
+    |
+163 |     #[pin_project(project)] //~ ERROR expected `project = <identifier>`, found `project`
+    |                   ^^^^^^^
+
+error: expected `project = <identifier>`, found `project =`
+   --> tests/ui/pin_project/invalid.rs:166:19
+    |
+166 |     #[pin_project(project = )] //~ ERROR expected `project = <identifier>`, found `project =`
+    |                   ^^^^^^^^^
+
+error: expected identifier
+   --> tests/ui/pin_project/invalid.rs:169:29
+    |
+169 |     #[pin_project(project = !)] //~ ERROR expected identifier
+    |                             ^
+
+error: expected `project_ref = <identifier>`, found `project_ref`
+   --> tests/ui/pin_project/invalid.rs:172:19
+    |
+172 |     #[pin_project(project_ref)] //~ ERROR expected `project_ref = <identifier>`, found `project_ref`
+    |                   ^^^^^^^^^^^
+
+error: expected `project_ref = <identifier>`, found `project_ref =`
+   --> tests/ui/pin_project/invalid.rs:175:19
+    |
+175 |     #[pin_project(project_ref = )] //~ ERROR expected `project_ref = <identifier>`, found `project_ref =`
+    |                   ^^^^^^^^^^^^^
+
+error: expected identifier
+   --> tests/ui/pin_project/invalid.rs:178:33
+    |
+178 |     #[pin_project(project_ref = !)] //~ ERROR expected identifier
+    |                                 ^
+
+error: expected `project_replace = <identifier>`, found `project_replace =`
+   --> tests/ui/pin_project/invalid.rs:184:19
+    |
+184 |     #[pin_project(project_replace = )] //~ ERROR expected `project_replace = <identifier>`, found `project_replace =`
+    |                   ^^^^^^^^^^^^^^^^^
+
+error: expected identifier
+   --> tests/ui/pin_project/invalid.rs:187:37
+    |
+187 |     #[pin_project(project_replace = !)] //~ ERROR expected identifier
+    |                                     ^
+
+error: `project_replace` argument requires a value when used on enums
+   --> tests/ui/pin_project/invalid.rs:190:19
+    |
+190 |     #[pin_project(project_replace)] //~ ERROR `project_replace` argument requires a value when used on enums
+    |                   ^^^^^^^^^^^^^^^
+
+error: name `OrigAndProj` is the same as the original type name
+   --> tests/ui/pin_project/invalid.rs:199:29
+    |
+199 |     #[pin_project(project = OrigAndProj)] //~ ERROR name `OrigAndProj` is the same as the original type name
+    |                             ^^^^^^^^^^^
+
+error: name `OrigAndProjRef` is the same as the original type name
+   --> tests/ui/pin_project/invalid.rs:202:33
+    |
+202 |     #[pin_project(project_ref = OrigAndProjRef)] //~ ERROR name `OrigAndProjRef` is the same as the original type name
+    |                                 ^^^^^^^^^^^^^^
+
+error: name `OrigAndProjOwn` is the same as the original type name
+   --> tests/ui/pin_project/invalid.rs:205:37
+    |
+205 |     #[pin_project(project_replace = OrigAndProjOwn)] //~ ERROR name `OrigAndProjOwn` is the same as the original type name
+    |                                     ^^^^^^^^^^^^^^
+
+error: name `A` is already specified by `project` argument
+   --> tests/ui/pin_project/invalid.rs:208:46
+    |
+208 |     #[pin_project(project = A, project_ref = A)] //~ ERROR name `A` is already specified by `project` argument
+    |                                              ^
+
+error: name `A` is already specified by `project` argument
+   --> tests/ui/pin_project/invalid.rs:211:50
+    |
+211 |     #[pin_project(project = A, project_replace = A)] //~ ERROR name `A` is already specified by `project` argument
+    |                                                  ^
+
+error: name `A` is already specified by `project_ref` argument
+   --> tests/ui/pin_project/invalid.rs:214:54
+    |
+214 |     #[pin_project(project_ref = A, project_replace = A)] //~ ERROR name `A` is already specified by `project_ref` argument
+    |                                                      ^
+
+error: duplicate #[pin_project] attribute
+   --> tests/ui/pin_project/invalid.rs:222:5
+    |
+222 |     #[pin_project] //~ ERROR duplicate #[pin_project] attribute
+    |     ^^^^^^^^^^^^^^
+
+error: #[pin_project] attribute may not be used on structs with zero fields
+   --> tests/ui/pin_project/invalid.rs:230:19
+    |
+230 |     struct Struct {} //~ ERROR may not be used on structs with zero fields
+    |                   ^^
+
+error: #[pin_project] attribute may not be used on structs with zero fields
+   --> tests/ui/pin_project/invalid.rs:233:23
+    |
+233 |     struct TupleStruct(); //~ ERROR may not be used on structs with zero fields
+    |                       ^^
+
+error: #[pin_project] attribute may not be used on structs with zero fields
+   --> tests/ui/pin_project/invalid.rs:236:12
+    |
+236 |     struct UnitStruct; //~ ERROR may not be used on structs with zero fields
+    |            ^^^^^^^^^^
+
+error: #[pin_project] attribute may not be used on enums without variants
+   --> tests/ui/pin_project/invalid.rs:239:20
+    |
+239 |     enum EnumEmpty {} //~ ERROR may not be used on enums without variants
+    |                    ^^
+
+error: #[pin_project] attribute may not be used on enums with discriminants
+   --> tests/ui/pin_project/invalid.rs:243:13
+    |
+243 |         V = 2, //~ ERROR may not be used on enums with discriminants
+    |             ^
+
+error: #[pin_project] attribute may not be used on enums with zero fields
+   --> tests/ui/pin_project/invalid.rs:248:9
+    |
+248 | /         Unit, //~ ERROR may not be used on enums with zero fields
+249 | |         Tuple(),
+250 | |         Struct {},
+    | |__________________^
+
+error: #[pin_project] attribute may only be used on structs or enums
+   --> tests/ui/pin_project/invalid.rs:254:5
+    |
+254 | /     union Union {
+255 | |         //~^ ERROR may only be used on structs or enums
+256 | |         f: (),
+257 | |     }
+    | |_____^
+
+error: #[pin_project] attribute may only be used on structs or enums
+   --> tests/ui/pin_project/invalid.rs:260:5
+    |
+260 |     impl Impl {} //~ ERROR may only be used on structs or enums
+    |     ^^^^^^^^^^^^
+
+error: #[pin_project] attribute may not be used on #[repr(packed)] types
+   --> tests/ui/pin_project/invalid.rs:268:12
+    |
+268 |     #[repr(packed)]
+    |            ^^^^^^
+
+error: #[pin_project] attribute may not be used on #[repr(packed)] types
+   --> tests/ui/pin_project/invalid.rs:272:12
+    |
+272 |     #[repr(packed)]
+    |            ^^^^^^
+
+error: #[pin_project] attribute may not be used on #[repr(packed)] types
+   --> tests/ui/pin_project/invalid.rs:276:12
+    |
+276 |     #[repr(packed)]
+    |            ^^^^^^
diff --git a/tests/ui/pin_project/overlapping_unpin_struct.rs b/tests/ui/pin_project/overlapping_unpin_struct.rs
new file mode 100644 (file)
index 0000000..abfd5d1
--- /dev/null
@@ -0,0 +1,19 @@
+use std::marker::PhantomPinned;
+
+use pin_project::pin_project;
+
+#[pin_project]
+struct S<T> {
+    #[pin]
+    f: T,
+}
+
+struct __S {}
+
+impl Unpin for __S {}
+
+fn is_unpin<T: Unpin>() {}
+
+fn main() {
+    is_unpin::<S<PhantomPinned>>(); //~ ERROR E0277
+}
diff --git a/tests/ui/pin_project/overlapping_unpin_struct.stderr b/tests/ui/pin_project/overlapping_unpin_struct.stderr
new file mode 100644 (file)
index 0000000..1bd200d
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0277]: `PhantomPinned` cannot be unpinned
+  --> tests/ui/pin_project/overlapping_unpin_struct.rs:18:5
+   |
+18 |     is_unpin::<S<PhantomPinned>>(); //~ ERROR E0277
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `_::__S<'_, PhantomPinned>`, the trait `Unpin` is not implemented for `PhantomPinned`
+   |
+   = note: consider using `Box::pin`
+note: required because it appears within the type `_::__S<'_, PhantomPinned>`
+  --> tests/ui/pin_project/overlapping_unpin_struct.rs:6:8
+   |
+6  | struct S<T> {
+   |        ^
+note: required because of the requirements on the impl of `Unpin` for `S<PhantomPinned>`
+  --> tests/ui/pin_project/overlapping_unpin_struct.rs:5:1
+   |
+5  | #[pin_project]
+   | ^^^^^^^^^^^^^^
+6  | struct S<T> {
+   |        ^^^^
+note: required by a bound in `is_unpin`
+  --> tests/ui/pin_project/overlapping_unpin_struct.rs:15:16
+   |
+15 | fn is_unpin<T: Unpin>() {}
+   |                ^^^^^ required by this bound in `is_unpin`
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/pin_project/override-priv-mod.rs b/tests/ui/pin_project/override-priv-mod.rs
new file mode 100644 (file)
index 0000000..890fd5b
--- /dev/null
@@ -0,0 +1,32 @@
+// https://discord.com/channels/273534239310479360/512792629516173323/870075511009857617
+
+extern crate pin_project as pin_project_orig;
+extern crate self as pin_project;
+
+pub use ::pin_project_orig::*;
+mod __private {
+    pub use ::pin_project_orig::__private::*;
+    pub trait Drop {}
+}
+
+use std::{marker::PhantomPinned, mem};
+
+#[pin_project] //~ ERROR conflicting implementations of trait `_::FooMustNotImplDrop`
+struct S {
+    #[pin]
+    f: (u8, PhantomPinned),
+}
+
+impl Drop for S {
+    fn drop(&mut self) {
+        let prev = &self.f.0 as *const _ as usize;
+        let moved = mem::take(&mut self.f); // move pinned field
+        let moved = &moved.0 as *const _ as usize;
+        assert_eq!(prev, moved); // panic
+    }
+}
+
+fn main() {
+    let mut x = Box::pin(S { f: (1, PhantomPinned) });
+    let _f = x.as_mut().project().f; // first mutable access
+}
diff --git a/tests/ui/pin_project/override-priv-mod.stderr b/tests/ui/pin_project/override-priv-mod.stderr
new file mode 100644 (file)
index 0000000..8a3fb9b
--- /dev/null
@@ -0,0 +1,10 @@
+error[E0119]: conflicting implementations of trait `_::SMustNotImplDrop` for type `S`
+  --> tests/ui/pin_project/override-priv-mod.rs:14:1
+   |
+14 | #[pin_project] //~ ERROR conflicting implementations of trait `_::FooMustNotImplDrop`
+   | ^^^^^^^^^^^^^^
+   | |
+   | first implementation here
+   | conflicting implementation for `S`
+   |
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/pin_project/packed-enum.rs b/tests/ui/pin_project/packed-enum.rs
new file mode 100644 (file)
index 0000000..023c08d
--- /dev/null
@@ -0,0 +1,24 @@
+use pin_project::pin_project;
+
+// #[repr(packed)] cannot be apply on enums and will be rejected by rustc.
+// However, we should not rely on the behavior of rustc that rejects this.
+// https://github.com/taiki-e/pin-project/pull/324#discussion_r612388001
+
+#[repr(packed)] //~ ERROR E0517
+enum E1 {
+    V(()),
+}
+
+#[pin_project]
+#[repr(packed)] //~ ERROR E0517
+enum E2 {
+    V(()),
+}
+
+#[repr(packed)] //~ ERROR E0517
+#[pin_project]
+enum E3 {
+    V(()),
+}
+
+fn main() {}
diff --git a/tests/ui/pin_project/packed-enum.stderr b/tests/ui/pin_project/packed-enum.stderr
new file mode 100644 (file)
index 0000000..1872211
--- /dev/null
@@ -0,0 +1,42 @@
+error: #[repr(packed)] attribute should be applied to a struct or union
+  --> tests/ui/pin_project/packed-enum.rs:13:8
+   |
+13 | #[repr(packed)] //~ ERROR E0517
+   |        ^^^^^^
+
+error: #[repr(packed)] attribute should be applied to a struct or union
+  --> tests/ui/pin_project/packed-enum.rs:18:8
+   |
+18 | #[repr(packed)] //~ ERROR E0517
+   |        ^^^^^^
+
+error[E0517]: attribute should be applied to a struct or union
+  --> tests/ui/pin_project/packed-enum.rs:7:8
+   |
+7  |   #[repr(packed)] //~ ERROR E0517
+   |          ^^^^^^
+8  | / enum E1 {
+9  | |     V(()),
+10 | | }
+   | |_- not a struct or union
+
+error[E0517]: attribute should be applied to a struct or union
+  --> tests/ui/pin_project/packed-enum.rs:13:8
+   |
+13 |   #[repr(packed)] //~ ERROR E0517
+   |          ^^^^^^
+14 | / enum E2 {
+15 | |     V(()),
+16 | | }
+   | |_- not a struct or union
+
+error[E0517]: attribute should be applied to a struct or union
+  --> tests/ui/pin_project/packed-enum.rs:18:8
+   |
+18 |   #[repr(packed)] //~ ERROR E0517
+   |          ^^^^^^
+19 |   #[pin_project]
+20 | / enum E3 {
+21 | |     V(()),
+22 | | }
+   | |_- not a struct or union
diff --git a/tests/ui/pin_project/packed-name-value.rs b/tests/ui/pin_project/packed-name-value.rs
new file mode 100644 (file)
index 0000000..dedc403
--- /dev/null
@@ -0,0 +1,27 @@
+use pin_project::pin_project;
+
+// #[repr(packed = "")] is not valid format of #[repr(packed)] and will be
+// rejected by rustc.
+// However, we should not rely on the behavior of rustc that rejects this.
+// https://github.com/taiki-e/pin-project/pull/324#discussion_r612388001
+
+// https://github.com/taiki-e/pin-project/pull/324#discussion_r612388001
+// https://github.com/rust-lang/rust/issues/83921
+// #[repr(packed = "")] //~ ERROR E0552
+// struct S1 {
+//     f: (),
+// }
+
+#[pin_project]
+#[repr(packed = "")] //~ ERROR attribute should not be name-value pair
+struct S2 {
+    f: (),
+}
+
+#[repr(packed = "")] //~ ERROR attribute should not be name-value pair
+#[pin_project]
+struct S3 {
+    f: (),
+}
+
+fn main() {}
diff --git a/tests/ui/pin_project/packed-name-value.stderr b/tests/ui/pin_project/packed-name-value.stderr
new file mode 100644 (file)
index 0000000..d8b2194
--- /dev/null
@@ -0,0 +1,23 @@
+error: #[repr(packed)] attribute should not be name-value pair
+  --> tests/ui/pin_project/packed-name-value.rs:16:8
+   |
+16 | #[repr(packed = "")] //~ ERROR attribute should not be name-value pair
+   |        ^^^^^^^^^^^
+
+error: #[repr(packed)] attribute should not be name-value pair
+  --> tests/ui/pin_project/packed-name-value.rs:21:8
+   |
+21 | #[repr(packed = "")] //~ ERROR attribute should not be name-value pair
+   |        ^^^^^^^^^^^
+
+error[E0693]: incorrect `repr(packed)` attribute format
+  --> tests/ui/pin_project/packed-name-value.rs:16:8
+   |
+16 | #[repr(packed = "")] //~ ERROR attribute should not be name-value pair
+   |        ^^^^^^^^^^^ help: use parentheses instead: `packed()`
+
+error[E0693]: incorrect `repr(packed)` attribute format
+  --> tests/ui/pin_project/packed-name-value.rs:21:8
+   |
+21 | #[repr(packed = "")] //~ ERROR attribute should not be name-value pair
+   |        ^^^^^^^^^^^ help: use parentheses instead: `packed()`
diff --git a/tests/ui/pin_project/packed.rs b/tests/ui/pin_project/packed.rs
new file mode 100644 (file)
index 0000000..dd3ebfd
--- /dev/null
@@ -0,0 +1,33 @@
+use pin_project::pin_project;
+
+#[pin_project]
+#[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] types
+struct Packed1 {
+    #[pin]
+    f: u8,
+}
+
+// Test putting 'repr' before the 'pin_project' attribute
+#[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] types
+#[pin_project]
+struct Packed2 {
+    #[pin]
+    f: u8,
+}
+
+#[pin_project]
+#[repr(packed(2))] //~ ERROR may not be used on #[repr(packed)] types
+struct PackedN1 {
+    #[pin]
+    f: u32,
+}
+
+// Test putting 'repr' before the 'pin_project' attribute
+#[repr(packed(2))] //~ ERROR may not be used on #[repr(packed)] types
+#[pin_project]
+struct PackedN2 {
+    #[pin]
+    f: u32,
+}
+
+fn main() {}
diff --git a/tests/ui/pin_project/packed.stderr b/tests/ui/pin_project/packed.stderr
new file mode 100644 (file)
index 0000000..25ea5f4
--- /dev/null
@@ -0,0 +1,23 @@
+error: #[pin_project] attribute may not be used on #[repr(packed)] types
+ --> tests/ui/pin_project/packed.rs:4:8
+  |
+4 | #[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] types
+  |        ^^^^^^
+
+error: #[pin_project] attribute may not be used on #[repr(packed)] types
+  --> tests/ui/pin_project/packed.rs:11:8
+   |
+11 | #[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] types
+   |        ^^^^^^
+
+error: #[pin_project] attribute may not be used on #[repr(packed)] types
+  --> tests/ui/pin_project/packed.rs:19:8
+   |
+19 | #[repr(packed(2))] //~ ERROR may not be used on #[repr(packed)] types
+   |        ^^^^^^^^^
+
+error: #[pin_project] attribute may not be used on #[repr(packed)] types
+  --> tests/ui/pin_project/packed.rs:26:8
+   |
+26 | #[repr(packed(2))] //~ ERROR may not be used on #[repr(packed)] types
+   |        ^^^^^^^^^
diff --git a/tests/ui/pin_project/packed_sneaky-1.rs b/tests/ui/pin_project/packed_sneaky-1.rs
new file mode 100644 (file)
index 0000000..83a4612
--- /dev/null
@@ -0,0 +1,41 @@
+use std::pin::Pin;
+
+use auxiliary_macro::{hidden_repr, hidden_repr2};
+use pin_project::{pin_project, pinned_drop, UnsafeUnpin};
+
+#[pin_project] //~ ERROR may not be used on #[repr(packed)] types
+#[hidden_repr(packed)]
+struct A {
+    #[pin]
+    f: u32,
+}
+
+#[hidden_repr2]
+#[pin_project] //~ ERROR may not be used on #[repr(packed)] types
+struct B {
+    #[pin]
+    f: u32,
+}
+
+#[pin_project(UnsafeUnpin)] //~ ERROR may not be used on #[repr(packed)] types
+#[hidden_repr(packed)]
+struct C {
+    #[pin]
+    f: u32,
+}
+
+unsafe impl UnsafeUnpin for C {}
+
+#[pin_project(PinnedDrop)] //~ ERROR may not be used on #[repr(packed)] types
+#[hidden_repr(packed)]
+struct D {
+    #[pin]
+    f: u32,
+}
+
+#[pinned_drop]
+impl PinnedDrop for D {
+    fn drop(self: Pin<&mut Self>) {}
+}
+
+fn main() {}
diff --git a/tests/ui/pin_project/packed_sneaky-1.stderr b/tests/ui/pin_project/packed_sneaky-1.stderr
new file mode 100644 (file)
index 0000000..0746e1a
--- /dev/null
@@ -0,0 +1,25 @@
+error: #[pin_project] attribute may not be used on #[repr(packed)] types
+ --> tests/ui/pin_project/packed_sneaky-1.rs:7:15
+  |
+7 | #[hidden_repr(packed)]
+  |               ^^^^^^
+
+error: #[pin_project] attribute may not be used on #[repr(packed)] types
+  --> tests/ui/pin_project/packed_sneaky-1.rs:13:1
+   |
+13 | #[hidden_repr2]
+   | ^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in the attribute macro `hidden_repr2` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: #[pin_project] attribute may not be used on #[repr(packed)] types
+  --> tests/ui/pin_project/packed_sneaky-1.rs:21:15
+   |
+21 | #[hidden_repr(packed)]
+   |               ^^^^^^
+
+error: #[pin_project] attribute may not be used on #[repr(packed)] types
+  --> tests/ui/pin_project/packed_sneaky-1.rs:30:15
+   |
+30 | #[hidden_repr(packed)]
+   |               ^^^^^^
diff --git a/tests/ui/pin_project/packed_sneaky-2.rs b/tests/ui/pin_project/packed_sneaky-2.rs
new file mode 100644 (file)
index 0000000..b098358
--- /dev/null
@@ -0,0 +1,12 @@
+use auxiliary_macro::hidden_repr_macro;
+use pin_project::pin_project;
+
+hidden_repr_macro! { //~ ERROR may not be used on #[repr(packed)] types
+    #[pin_project]
+    struct B {
+        #[pin]
+        f: u32,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/pin_project/packed_sneaky-2.stderr b/tests/ui/pin_project/packed_sneaky-2.stderr
new file mode 100644 (file)
index 0000000..d643052
--- /dev/null
@@ -0,0 +1,13 @@
+error: #[pin_project] attribute may not be used on #[repr(packed)] types
+  --> tests/ui/pin_project/packed_sneaky-2.rs:4:1
+   |
+4  | / hidden_repr_macro! { //~ ERROR may not be used on #[repr(packed)] types
+5  | |     #[pin_project]
+6  | |     struct B {
+7  | |         #[pin]
+8  | |         f: u32,
+9  | |     }
+10 | | }
+   | |_^
+   |
+   = note: this error originates in the macro `hidden_repr_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/pin_project/packed_sneaky-3.rs b/tests/ui/pin_project/packed_sneaky-3.rs
new file mode 100644 (file)
index 0000000..d3f00f3
--- /dev/null
@@ -0,0 +1,32 @@
+use auxiliary_macro::{hidden_repr_macro, HiddenRepr};
+use pin_project::pin_project;
+
+hidden_repr_macro! {} //~ ERROR expected item after attributes
+#[pin_project]
+struct S1 {
+    #[pin]
+    f: u32,
+}
+
+macro_rules! hidden_repr_macro2 {
+    () => {
+        #[repr(packed)] //~ ERROR expected item after attributes
+    };
+}
+
+hidden_repr_macro2! {}
+#[pin_project]
+struct S2 {
+    #[pin]
+    f: u32,
+}
+
+#[derive(HiddenRepr)] //~ ERROR expected item after attributes
+struct S3 {}
+#[pin_project]
+struct S4 {
+    #[pin]
+    f: u32,
+}
+
+fn main() {}
diff --git a/tests/ui/pin_project/packed_sneaky-3.stderr b/tests/ui/pin_project/packed_sneaky-3.stderr
new file mode 100644 (file)
index 0000000..c97f18b
--- /dev/null
@@ -0,0 +1,32 @@
+error: expected item after attributes
+ --> tests/ui/pin_project/packed_sneaky-3.rs:4:1
+  |
+4 | hidden_repr_macro! {} //~ ERROR expected item after attributes
+  | ^^^^^^^^^^^^^^^^^^^^^
+  |
+  = note: this error originates in the macro `hidden_repr_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: expected item after attributes
+  --> tests/ui/pin_project/packed_sneaky-3.rs:13:9
+   |
+13 |         #[repr(packed)] //~ ERROR expected item after attributes
+   |         ^^^^^^^^^^^^^^^
+...
+17 | hidden_repr_macro2! {}
+   | ---------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `hidden_repr_macro2` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: expected item after attributes
+  --> tests/ui/pin_project/packed_sneaky-3.rs:24:10
+   |
+24 | #[derive(HiddenRepr)] //~ ERROR expected item after attributes
+   |          ^^^^^^^^^^
+   |
+   = note: this error originates in the derive macro `HiddenRepr` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: proc-macro derive produced unparseable tokens
+  --> tests/ui/pin_project/packed_sneaky-3.rs:24:10
+   |
+24 | #[derive(HiddenRepr)] //~ ERROR expected item after attributes
+   |          ^^^^^^^^^^
diff --git a/tests/ui/pin_project/packed_sneaky-4.rs b/tests/ui/pin_project/packed_sneaky-4.rs
new file mode 100644 (file)
index 0000000..fb954ba
--- /dev/null
@@ -0,0 +1,15 @@
+// https://github.com/taiki-e/pin-project/issues/342
+
+#![allow(unaligned_references)]
+
+use auxiliary_macro::hidden_repr2;
+use pin_project::pin_project;
+
+#[pin_project] //~ ERROR reference to packed field is unaligned
+#[hidden_repr2]
+struct A {
+    #[pin]
+    f: u32,
+}
+
+fn main() {}
diff --git a/tests/ui/pin_project/packed_sneaky-4.stderr b/tests/ui/pin_project/packed_sneaky-4.stderr
new file mode 100644 (file)
index 0000000..8072ce2
--- /dev/null
@@ -0,0 +1,16 @@
+error: reference to packed field is unaligned
+ --> tests/ui/pin_project/packed_sneaky-4.rs:8:1
+  |
+8 | #[pin_project] //~ ERROR reference to packed field is unaligned
+  | ^^^^^^^^^^^^^^
+  |
+note: the lint level is defined here
+ --> tests/ui/pin_project/packed_sneaky-4.rs:8:1
+  |
+8 | #[pin_project] //~ ERROR reference to packed field is unaligned
+  | ^^^^^^^^^^^^^^
+  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+  = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+  = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+  = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+  = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/pin_project/private_in_public-enum.rs b/tests/ui/pin_project/private_in_public-enum.rs
new file mode 100644 (file)
index 0000000..15a82a9
--- /dev/null
@@ -0,0 +1,23 @@
+// Even if allows private_in_public, these are errors.
+
+#![allow(private_in_public)]
+
+pub enum PublicEnum {
+    V(PrivateEnum), //~ ERROR E0446
+}
+
+enum PrivateEnum {
+    V(u8),
+}
+
+mod foo {
+    pub(crate) enum CrateEnum {
+        V(PrivateEnum), //~ ERROR E0446
+    }
+
+    enum PrivateEnum {
+        V(u8),
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/pin_project/private_in_public-enum.stderr b/tests/ui/pin_project/private_in_public-enum.stderr
new file mode 100644 (file)
index 0000000..c93b265
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0446]: private type `PrivateEnum` in public interface
+ --> tests/ui/pin_project/private_in_public-enum.rs:6:7
+  |
+6 |     V(PrivateEnum), //~ ERROR E0446
+  |       ^^^^^^^^^^^ can't leak private type
+...
+9 | enum PrivateEnum {
+  | ---------------- `PrivateEnum` declared as private
+
+error[E0446]: private type `foo::PrivateEnum` in public interface
+  --> tests/ui/pin_project/private_in_public-enum.rs:15:11
+   |
+15 |         V(PrivateEnum), //~ ERROR E0446
+   |           ^^^^^^^^^^^ can't leak private type
+...
+18 |     enum PrivateEnum {
+   |     ---------------- `foo::PrivateEnum` declared as private
diff --git a/tests/ui/pin_project/project_replace_unsized.rs b/tests/ui/pin_project/project_replace_unsized.rs
new file mode 100644 (file)
index 0000000..20dde12
--- /dev/null
@@ -0,0 +1,11 @@
+use pin_project::pin_project;
+
+#[pin_project(project_replace)] //~ ERROR E0277
+struct Struct<T: ?Sized> {
+    f: T,
+}
+
+#[pin_project(project_replace)] //~ ERROR E0277
+struct TupleStruct<T: ?Sized>(T);
+
+fn main() {}
diff --git a/tests/ui/pin_project/project_replace_unsized.stderr b/tests/ui/pin_project/project_replace_unsized.stderr
new file mode 100644 (file)
index 0000000..042b499
--- /dev/null
@@ -0,0 +1,118 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> tests/ui/pin_project/project_replace_unsized.rs:3:15
+  |
+3 | #[pin_project(project_replace)] //~ ERROR E0277
+  |               ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+4 | struct Struct<T: ?Sized> {
+  |               - this type parameter needs to be `std::marker::Sized`
+  |
+note: required because it appears within the type `Struct<T>`
+ --> tests/ui/pin_project/project_replace_unsized.rs:4:8
+  |
+4 | struct Struct<T: ?Sized> {
+  |        ^^^^^^
+  = help: unsized fn params are gated as an unstable feature
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+  |
+4 - struct Struct<T: ?Sized> {
+4 + struct Struct<T> {
+  |
+help: function arguments must have a statically known size, borrowed types always have a known size
+  |
+3 | #[pin_project(&project_replace)] //~ ERROR E0277
+  |               +
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+   --> tests/ui/pin_project/project_replace_unsized.rs:3:1
+    |
+3   | #[pin_project(project_replace)] //~ ERROR E0277
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+4   | struct Struct<T: ?Sized> {
+    |               - this type parameter needs to be `std::marker::Sized`
+    |
+note: required because it appears within the type `Struct<T>`
+   --> tests/ui/pin_project/project_replace_unsized.rs:4:8
+    |
+4   | struct Struct<T: ?Sized> {
+    |        ^^^^^^
+note: required by a bound in `UnsafeOverwriteGuard::<T>::new`
+   --> src/lib.rs
+    |
+    |     impl<T> UnsafeOverwriteGuard<T> {
+    |          ^ required by this bound in `UnsafeOverwriteGuard::<T>::new`
+    = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+    |
+4   - struct Struct<T: ?Sized> {
+4   + struct Struct<T> {
+    |
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+    --> tests/ui/pin_project/project_replace_unsized.rs:5:5
+     |
+3    | #[pin_project(project_replace)] //~ ERROR E0277
+     | ------------------------------- required by a bound introduced by this call
+4    | struct Struct<T: ?Sized> {
+     |               - this type parameter needs to be `std::marker::Sized`
+5    |     f: T,
+     |     ^ doesn't have a size known at compile-time
+     |
+note: required by a bound in `std::ptr::read`
+    --> $RUST/core/src/ptr/mod.rs
+     |
+     | pub const unsafe fn read<T>(src: *const T) -> T {
+     |                          ^ required by this bound in `std::ptr::read`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+     |
+4    - struct Struct<T: ?Sized> {
+4    + struct Struct<T> {
+     |
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> tests/ui/pin_project/project_replace_unsized.rs:8:15
+  |
+8 | #[pin_project(project_replace)] //~ ERROR E0277
+  |               ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+9 | struct TupleStruct<T: ?Sized>(T);
+  |                    - this type parameter needs to be `std::marker::Sized`
+  |
+note: required because it appears within the type `TupleStruct<T>`
+ --> tests/ui/pin_project/project_replace_unsized.rs:9:8
+  |
+9 | struct TupleStruct<T: ?Sized>(T);
+  |        ^^^^^^^^^^^
+  = help: unsized fn params are gated as an unstable feature
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+  |
+9 - struct TupleStruct<T: ?Sized>(T);
+9 + struct TupleStruct<T>(T);
+  |
+help: function arguments must have a statically known size, borrowed types always have a known size
+  |
+8 | #[pin_project(&project_replace)] //~ ERROR E0277
+  |               +
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+   --> tests/ui/pin_project/project_replace_unsized.rs:8:1
+    |
+8   | #[pin_project(project_replace)] //~ ERROR E0277
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+9   | struct TupleStruct<T: ?Sized>(T);
+    |                    - this type parameter needs to be `std::marker::Sized`
+    |
+note: required because it appears within the type `TupleStruct<T>`
+   --> tests/ui/pin_project/project_replace_unsized.rs:9:8
+    |
+9   | struct TupleStruct<T: ?Sized>(T);
+    |        ^^^^^^^^^^^
+note: required by a bound in `UnsafeOverwriteGuard::<T>::new`
+   --> src/lib.rs
+    |
+    |     impl<T> UnsafeOverwriteGuard<T> {
+    |          ^ required by this bound in `UnsafeOverwriteGuard::<T>::new`
+    = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+    |
+9   - struct TupleStruct<T: ?Sized>(T);
+9   + struct TupleStruct<T>(T);
+    |
diff --git a/tests/ui/pin_project/project_replace_unsized_fn_params.rs b/tests/ui/pin_project/project_replace_unsized_fn_params.rs
new file mode 100644 (file)
index 0000000..e0fa25b
--- /dev/null
@@ -0,0 +1,13 @@
+#![feature(unsized_fn_params)]
+
+use pin_project::pin_project;
+
+#[pin_project(project_replace)] //~ ERROR E0277
+struct Struct<T: ?Sized> {
+    f: T,
+}
+
+#[pin_project(project_replace)] //~ ERROR E0277
+struct TupleStruct<T: ?Sized>(T);
+
+fn main() {}
diff --git a/tests/ui/pin_project/project_replace_unsized_fn_params.stderr b/tests/ui/pin_project/project_replace_unsized_fn_params.stderr
new file mode 100644 (file)
index 0000000..10fad08
--- /dev/null
@@ -0,0 +1,112 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+ --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:6:8
+  |
+6 | struct Struct<T: ?Sized> {
+  |        ^^^^^^^-^^^^^^^^^
+  |        |      |
+  |        |      this type parameter needs to be `std::marker::Sized`
+  |        doesn't have a size known at compile-time
+  |
+note: required because it appears within the type `__StructProjectionOwned<T>`
+ --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:6:8
+  |
+6 | struct Struct<T: ?Sized> {
+  |        ^^^^^^
+  = note: the return type of a function must have a statically known size
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+  |
+6 - struct Struct<T: ?Sized> {
+6 + struct Struct<T> {
+  |
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+   --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:5:1
+    |
+5   | #[pin_project(project_replace)] //~ ERROR E0277
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+6   | struct Struct<T: ?Sized> {
+    |               - this type parameter needs to be `std::marker::Sized`
+    |
+note: required because it appears within the type `Struct<T>`
+   --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:6:8
+    |
+6   | struct Struct<T: ?Sized> {
+    |        ^^^^^^
+note: required by a bound in `UnsafeOverwriteGuard::<T>::new`
+   --> src/lib.rs
+    |
+    |     impl<T> UnsafeOverwriteGuard<T> {
+    |          ^ required by this bound in `UnsafeOverwriteGuard::<T>::new`
+    = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+    |
+6   - struct Struct<T: ?Sized> {
+6   + struct Struct<T> {
+    |
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+    --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:7:5
+     |
+5    | #[pin_project(project_replace)] //~ ERROR E0277
+     | ------------------------------- required by a bound introduced by this call
+6    | struct Struct<T: ?Sized> {
+     |               - this type parameter needs to be `std::marker::Sized`
+7    |     f: T,
+     |     ^ doesn't have a size known at compile-time
+     |
+note: required by a bound in `std::ptr::read`
+    --> $RUST/core/src/ptr/mod.rs
+     |
+     | pub const unsafe fn read<T>(src: *const T) -> T {
+     |                          ^ required by this bound in `std::ptr::read`
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+     |
+6    - struct Struct<T: ?Sized> {
+6    + struct Struct<T> {
+     |
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:11:8
+   |
+11 | struct TupleStruct<T: ?Sized>(T);
+   |        ^^^^^^^^^^^^-^^^^^^^^^
+   |        |           |
+   |        |           this type parameter needs to be `std::marker::Sized`
+   |        doesn't have a size known at compile-time
+   |
+note: required because it appears within the type `__TupleStructProjectionOwned<T>`
+  --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:11:8
+   |
+11 | struct TupleStruct<T: ?Sized>(T);
+   |        ^^^^^^^^^^^
+   = note: the return type of a function must have a statically known size
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+11 - struct TupleStruct<T: ?Sized>(T);
+11 + struct TupleStruct<T>(T);
+   |
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+   --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:10:1
+    |
+10  | #[pin_project(project_replace)] //~ ERROR E0277
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+11  | struct TupleStruct<T: ?Sized>(T);
+    |                    - this type parameter needs to be `std::marker::Sized`
+    |
+note: required because it appears within the type `TupleStruct<T>`
+   --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:11:8
+    |
+11  | struct TupleStruct<T: ?Sized>(T);
+    |        ^^^^^^^^^^^
+note: required by a bound in `UnsafeOverwriteGuard::<T>::new`
+   --> src/lib.rs
+    |
+    |     impl<T> UnsafeOverwriteGuard<T> {
+    |          ^ required by this bound in `UnsafeOverwriteGuard::<T>::new`
+    = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+    |
+11  - struct TupleStruct<T: ?Sized>(T);
+11  + struct TupleStruct<T>(T);
+    |
diff --git a/tests/ui/pin_project/remove-attr-from-field.rs b/tests/ui/pin_project/remove-attr-from-field.rs
new file mode 100644 (file)
index 0000000..fd14da3
--- /dev/null
@@ -0,0 +1,33 @@
+use std::{marker::PhantomPinned, pin::Pin};
+
+use auxiliary_macro::remove_attr;
+use pin_project::pin_project;
+
+fn is_unpin<T: Unpin>() {}
+
+#[pin_project]
+#[remove_attr(field_all)]
+struct A {
+    #[pin]
+    f: PhantomPinned,
+}
+
+#[remove_attr(field_all)]
+#[pin_project]
+struct B {
+    #[pin]
+    f: PhantomPinned,
+}
+
+fn main() {
+    is_unpin::<A>();
+    is_unpin::<B>();
+
+    let mut x = A { f: PhantomPinned };
+    let x = Pin::new(&mut x).project();
+    let _: Pin<&mut PhantomPinned> = x.f; //~ ERROR E0308
+
+    let mut x = B { f: PhantomPinned };
+    let x = Pin::new(&mut x).project();
+    let _: Pin<&mut PhantomPinned> = x.f; //~ ERROR E0308
+}
diff --git a/tests/ui/pin_project/remove-attr-from-field.stderr b/tests/ui/pin_project/remove-attr-from-field.stderr
new file mode 100644 (file)
index 0000000..697cd63
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> tests/ui/pin_project/remove-attr-from-field.rs:28:38
+   |
+28 |     let _: Pin<&mut PhantomPinned> = x.f; //~ ERROR E0308
+   |            -----------------------   ^^^ expected struct `Pin`, found `&mut PhantomPinned`
+   |            |
+   |            expected due to this
+   |
+   = note:         expected struct `Pin<&mut PhantomPinned>`
+           found mutable reference `&mut PhantomPinned`
+
+error[E0308]: mismatched types
+  --> tests/ui/pin_project/remove-attr-from-field.rs:32:38
+   |
+32 |     let _: Pin<&mut PhantomPinned> = x.f; //~ ERROR E0308
+   |            -----------------------   ^^^ expected struct `Pin`, found `&mut PhantomPinned`
+   |            |
+   |            expected due to this
+   |
+   = note:         expected struct `Pin<&mut PhantomPinned>`
+           found mutable reference `&mut PhantomPinned`
diff --git a/tests/ui/pin_project/remove-attr-from-struct.rs b/tests/ui/pin_project/remove-attr-from-struct.rs
new file mode 100644 (file)
index 0000000..cbe5aba
--- /dev/null
@@ -0,0 +1,47 @@
+use std::{marker::PhantomPinned, pin::Pin};
+
+use auxiliary_macro::remove_attr;
+use pin_project::pin_project;
+
+fn is_unpin<T: Unpin>() {}
+
+#[pin_project]
+#[remove_attr(struct_all)]
+struct A {
+    #[pin] //~ ERROR cannot find attribute `pin` in this scope
+    f: PhantomPinned,
+}
+
+#[remove_attr(struct_all)]
+#[pin_project]
+struct B {
+    #[pin] //~ ERROR cannot find attribute `pin` in this scope
+    f: PhantomPinned,
+}
+
+#[pin_project] //~ ERROR has been removed
+#[remove_attr(struct_pin)]
+struct C {
+    f: PhantomPinned,
+}
+
+#[remove_attr(struct_pin)]
+#[pin_project] // Ok
+struct D {
+    f: PhantomPinned,
+}
+
+fn main() {
+    is_unpin::<A>(); //~ ERROR E0277
+    is_unpin::<B>(); //~ ERROR E0277
+    is_unpin::<D>(); // Ok
+
+    let mut x = A { f: PhantomPinned };
+    let _ = Pin::new(&mut x).project(); //~ ERROR E0277,E0599
+
+    let mut x = B { f: PhantomPinned };
+    let _ = Pin::new(&mut x).project(); //~ ERROR E0277,E0599
+
+    let mut x = D { f: PhantomPinned };
+    let _ = Pin::new(&mut x).project(); //~ Ok
+}
diff --git a/tests/ui/pin_project/remove-attr-from-struct.stderr b/tests/ui/pin_project/remove-attr-from-struct.stderr
new file mode 100644 (file)
index 0000000..1a9cd42
--- /dev/null
@@ -0,0 +1,107 @@
+error: #[pin_project] attribute has been removed
+  --> tests/ui/pin_project/remove-attr-from-struct.rs:22:1
+   |
+22 | #[pin_project] //~ ERROR has been removed
+   | ^^^^^^^^^^^^^^
+   |
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot find attribute `pin` in this scope
+  --> tests/ui/pin_project/remove-attr-from-struct.rs:18:7
+   |
+18 |     #[pin] //~ ERROR cannot find attribute `pin` in this scope
+   |       ^^^
+
+error: cannot find attribute `pin` in this scope
+  --> tests/ui/pin_project/remove-attr-from-struct.rs:11:7
+   |
+11 |     #[pin] //~ ERROR cannot find attribute `pin` in this scope
+   |       ^^^
+
+error[E0277]: `PhantomPinned` cannot be unpinned
+  --> tests/ui/pin_project/remove-attr-from-struct.rs:35:5
+   |
+35 |     is_unpin::<A>(); //~ ERROR E0277
+   |     ^^^^^^^^^^^^^ within `A`, the trait `Unpin` is not implemented for `PhantomPinned`
+   |
+   = note: consider using `Box::pin`
+note: required because it appears within the type `A`
+  --> tests/ui/pin_project/remove-attr-from-struct.rs:10:8
+   |
+10 | struct A {
+   |        ^
+note: required by a bound in `is_unpin`
+  --> tests/ui/pin_project/remove-attr-from-struct.rs:6:16
+   |
+6  | fn is_unpin<T: Unpin>() {}
+   |                ^^^^^ required by this bound in `is_unpin`
+
+error[E0277]: `PhantomPinned` cannot be unpinned
+  --> tests/ui/pin_project/remove-attr-from-struct.rs:36:5
+   |
+36 |     is_unpin::<B>(); //~ ERROR E0277
+   |     ^^^^^^^^^^^^^ within `B`, the trait `Unpin` is not implemented for `PhantomPinned`
+   |
+   = note: consider using `Box::pin`
+note: required because it appears within the type `B`
+  --> tests/ui/pin_project/remove-attr-from-struct.rs:17:8
+   |
+17 | struct B {
+   |        ^
+note: required by a bound in `is_unpin`
+  --> tests/ui/pin_project/remove-attr-from-struct.rs:6:16
+   |
+6  | fn is_unpin<T: Unpin>() {}
+   |                ^^^^^ required by this bound in `is_unpin`
+
+error[E0277]: `PhantomPinned` cannot be unpinned
+   --> tests/ui/pin_project/remove-attr-from-struct.rs:40:22
+    |
+40  |     let _ = Pin::new(&mut x).project(); //~ ERROR E0277,E0599
+    |             -------- ^^^^^^ within `A`, the trait `Unpin` is not implemented for `PhantomPinned`
+    |             |
+    |             required by a bound introduced by this call
+    |
+    = note: consider using `Box::pin`
+note: required because it appears within the type `A`
+   --> tests/ui/pin_project/remove-attr-from-struct.rs:10:8
+    |
+10  | struct A {
+    |        ^
+note: required by a bound in `Pin::<P>::new`
+   --> $RUST/core/src/pin.rs
+    |
+    | impl<P: Deref<Target: Unpin>> Pin<P> {
+    |                       ^^^^^ required by this bound in `Pin::<P>::new`
+
+error[E0599]: no method named `project` found for struct `Pin<&mut A>` in the current scope
+  --> tests/ui/pin_project/remove-attr-from-struct.rs:40:30
+   |
+40 |     let _ = Pin::new(&mut x).project(); //~ ERROR E0277,E0599
+   |                              ^^^^^^^ method not found in `Pin<&mut A>`
+
+error[E0277]: `PhantomPinned` cannot be unpinned
+   --> tests/ui/pin_project/remove-attr-from-struct.rs:43:22
+    |
+43  |     let _ = Pin::new(&mut x).project(); //~ ERROR E0277,E0599
+    |             -------- ^^^^^^ within `B`, the trait `Unpin` is not implemented for `PhantomPinned`
+    |             |
+    |             required by a bound introduced by this call
+    |
+    = note: consider using `Box::pin`
+note: required because it appears within the type `B`
+   --> tests/ui/pin_project/remove-attr-from-struct.rs:17:8
+    |
+17  | struct B {
+    |        ^
+note: required by a bound in `Pin::<P>::new`
+   --> $RUST/core/src/pin.rs
+    |
+    | impl<P: Deref<Target: Unpin>> Pin<P> {
+    |                       ^^^^^ required by this bound in `Pin::<P>::new`
+
+error[E0599]: no method named `project` found for struct `Pin<&mut B>` in the current scope
+  --> tests/ui/pin_project/remove-attr-from-struct.rs:43:30
+   |
+43 |     let _ = Pin::new(&mut x).project(); //~ ERROR E0277,E0599
+   |                              ^^^^^^^ method not found in `Pin<&mut B>`
diff --git a/tests/ui/pin_project/safe_packed_borrows.rs b/tests/ui/pin_project/safe_packed_borrows.rs
new file mode 100644 (file)
index 0000000..de8181c
--- /dev/null
@@ -0,0 +1,26 @@
+#![deny(renamed_and_removed_lints)]
+#![deny(safe_packed_borrows)] //~ ERROR has been renamed to `unaligned_references`
+#![allow(unaligned_references)]
+
+// This lint was removed in https://github.com/rust-lang/rust/pull/82525 (nightly-2021-03-28).
+// Refs:
+// - https://github.com/rust-lang/rust/pull/82525
+// - https://github.com/rust-lang/rust/issues/46043
+
+#[repr(packed)]
+struct Packed {
+    f: u32,
+}
+
+#[repr(packed(2))]
+struct PackedN {
+    f: u32,
+}
+
+fn main() {
+    let a = Packed { f: 1 };
+    let _ = &a.f;
+
+    let b = PackedN { f: 1 };
+    let _ = &b.f;
+}
diff --git a/tests/ui/pin_project/safe_packed_borrows.stderr b/tests/ui/pin_project/safe_packed_borrows.stderr
new file mode 100644 (file)
index 0000000..f483b6d
--- /dev/null
@@ -0,0 +1,11 @@
+error: lint `safe_packed_borrows` has been renamed to `unaligned_references`
+ --> tests/ui/pin_project/safe_packed_borrows.rs:2:9
+  |
+2 | #![deny(safe_packed_borrows)] //~ ERROR has been renamed to `unaligned_references`
+  |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `unaligned_references`
+  |
+note: the lint level is defined here
+ --> tests/ui/pin_project/safe_packed_borrows.rs:1:9
+  |
+1 | #![deny(renamed_and_removed_lints)]
+  |         ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/pin_project/unaligned_references.rs b/tests/ui/pin_project/unaligned_references.rs
new file mode 100644 (file)
index 0000000..eaf185d
--- /dev/null
@@ -0,0 +1,21 @@
+#![forbid(unaligned_references)]
+
+// Refs: https://github.com/rust-lang/rust/issues/82523
+
+#[repr(packed)]
+struct Packed {
+    f: u32,
+}
+
+#[repr(packed(2))]
+struct PackedN {
+    f: u32,
+}
+
+fn main() {
+    let a = Packed { f: 1 };
+    let _ = &a.f; //~ ERROR reference to packed field is unaligned
+
+    let b = PackedN { f: 1 };
+    let _ = &b.f; //~ ERROR reference to packed field is unaligned
+}
diff --git a/tests/ui/pin_project/unaligned_references.stderr b/tests/ui/pin_project/unaligned_references.stderr
new file mode 100644 (file)
index 0000000..8d5ddfc
--- /dev/null
@@ -0,0 +1,26 @@
+error: reference to packed field is unaligned
+  --> tests/ui/pin_project/unaligned_references.rs:17:13
+   |
+17 |     let _ = &a.f; //~ ERROR reference to packed field is unaligned
+   |             ^^^^
+   |
+note: the lint level is defined here
+  --> tests/ui/pin_project/unaligned_references.rs:1:11
+   |
+1  | #![forbid(unaligned_references)]
+   |           ^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
+
+error: reference to packed field is unaligned
+  --> tests/ui/pin_project/unaligned_references.rs:20:13
+   |
+20 |     let _ = &b.f; //~ ERROR reference to packed field is unaligned
+   |             ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
+   = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
+   = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
diff --git a/tests/ui/pin_project/unpin_sneaky.rs b/tests/ui/pin_project/unpin_sneaky.rs
new file mode 100644 (file)
index 0000000..3f5f32b
--- /dev/null
@@ -0,0 +1,11 @@
+use pin_project::pin_project;
+
+#[pin_project]
+struct S {
+    #[pin]
+    f: u8,
+}
+
+impl Unpin for __S {} //~ ERROR E0412,E0321
+
+fn main() {}
diff --git a/tests/ui/pin_project/unpin_sneaky.stderr b/tests/ui/pin_project/unpin_sneaky.stderr
new file mode 100644 (file)
index 0000000..82c2aa5
--- /dev/null
@@ -0,0 +1,5 @@
+error[E0412]: cannot find type `__S` in this scope
+ --> tests/ui/pin_project/unpin_sneaky.rs:9:16
+  |
+9 | impl Unpin for __S {} //~ ERROR E0412,E0321
+  |                ^^^ not found in this scope
diff --git a/tests/ui/pin_project/visibility.rs b/tests/ui/pin_project/visibility.rs
new file mode 100644 (file)
index 0000000..fdff5a6
--- /dev/null
@@ -0,0 +1,49 @@
+/// Only named projected types can be imported.
+/// See import_unnamed.rs for unnamed projected types.
+
+mod pub_ {
+    use pin_project::pin_project;
+
+    #[pin_project(project = DProj, project_ref = DProjRef)]
+    pub struct Default(());
+
+    #[pin_project(project = RProj, project_ref = RProjRef, project_replace = RProjOwn)]
+    pub struct Replace(());
+}
+pub mod pub_use {
+    #[rustfmt::skip]
+    pub use crate::pub_::DProj; //~ ERROR E0365
+    #[rustfmt::skip]
+    pub use crate::pub_::DProjRef; //~ ERROR E0365
+    #[rustfmt::skip]
+    pub use crate::pub_::RProj; //~ ERROR E0365
+    #[rustfmt::skip]
+    pub use crate::pub_::RProjOwn; //~ ERROR E0365
+    #[rustfmt::skip]
+    pub use crate::pub_::RProjRef; //~ ERROR E0365
+
+    // Confirm that the visibility of the original type is not changed.
+    pub use crate::pub_::{Default, Replace};
+}
+pub mod pub_use2 {
+    // Ok
+    #[allow(unused_imports)]
+    pub(crate) use crate::pub_::{DProj, DProjRef, RProj, RProjOwn, RProjRef};
+}
+
+mod pub_crate {
+    use pin_project::pin_project;
+
+    #[pin_project(project = DProj, project_ref = DProjRef)]
+    pub(crate) struct Default(());
+
+    #[pin_project(project = RProj, project_ref = RProjRef, project_replace = RProjOwn)]
+    pub(crate) struct Replace(());
+}
+pub mod pub_crate_use {
+    // Ok
+    #[allow(unused_imports)]
+    pub(crate) use crate::pub_crate::{DProj, DProjRef, RProj, RProjOwn, RProjRef};
+}
+
+fn main() {}
diff --git a/tests/ui/pin_project/visibility.stderr b/tests/ui/pin_project/visibility.stderr
new file mode 100644 (file)
index 0000000..4d1b722
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0365]: `DProj` is only public within the crate, and cannot be re-exported outside
+  --> tests/ui/pin_project/visibility.rs:15:13
+   |
+15 |     pub use crate::pub_::DProj; //~ ERROR E0365
+   |             ^^^^^^^^^^^^^^^^^^ re-export of crate public `DProj`
+   |
+   = note: consider declaring type or module `DProj` with `pub`
+
+error[E0365]: `DProjRef` is only public within the crate, and cannot be re-exported outside
+  --> tests/ui/pin_project/visibility.rs:17:13
+   |
+17 |     pub use crate::pub_::DProjRef; //~ ERROR E0365
+   |             ^^^^^^^^^^^^^^^^^^^^^ re-export of crate public `DProjRef`
+   |
+   = note: consider declaring type or module `DProjRef` with `pub`
+
+error[E0365]: `RProj` is only public within the crate, and cannot be re-exported outside
+  --> tests/ui/pin_project/visibility.rs:19:13
+   |
+19 |     pub use crate::pub_::RProj; //~ ERROR E0365
+   |             ^^^^^^^^^^^^^^^^^^ re-export of crate public `RProj`
+   |
+   = note: consider declaring type or module `RProj` with `pub`
+
+error[E0365]: `RProjOwn` is only public within the crate, and cannot be re-exported outside
+  --> tests/ui/pin_project/visibility.rs:21:13
+   |
+21 |     pub use crate::pub_::RProjOwn; //~ ERROR E0365
+   |             ^^^^^^^^^^^^^^^^^^^^^ re-export of crate public `RProjOwn`
+   |
+   = note: consider declaring type or module `RProjOwn` with `pub`
+
+error[E0365]: `RProjRef` is only public within the crate, and cannot be re-exported outside
+  --> tests/ui/pin_project/visibility.rs:23:13
+   |
+23 |     pub use crate::pub_::RProjRef; //~ ERROR E0365
+   |             ^^^^^^^^^^^^^^^^^^^^^ re-export of crate public `RProjRef`
+   |
+   = note: consider declaring type or module `RProjRef` with `pub`
diff --git a/tests/ui/pinned_drop/call-drop-inner.rs b/tests/ui/pinned_drop/call-drop-inner.rs
new file mode 100644 (file)
index 0000000..9f89942
--- /dev/null
@@ -0,0 +1,17 @@
+use std::pin::Pin;
+
+use pin_project::{pin_project, pinned_drop};
+
+#[pin_project(PinnedDrop)]
+struct Struct {
+    f: bool,
+}
+
+#[pinned_drop]
+impl PinnedDrop for Struct {
+    fn drop(mut self: Pin<&mut Self>) {
+        __drop_inner(__self);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/pinned_drop/call-drop-inner.stderr b/tests/ui/pinned_drop/call-drop-inner.stderr
new file mode 100644 (file)
index 0000000..e3ceebd
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+  --> tests/ui/pinned_drop/call-drop-inner.rs:13:9
+   |
+13 |         __drop_inner(__self);
+   |         ^^^^^^^^^^^^ ------ argument of type `Pin<&mut Struct>` unexpected
+   |
+note: function defined here
+  --> tests/ui/pinned_drop/call-drop-inner.rs:10:1
+   |
+10 | #[pinned_drop]
+   | ^^^^^^^^^^^^^^
+   = note: this error originates in the attribute macro `pinned_drop` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: remove the extra argument
+   |
+13 |         __drop_inner();
+   |         ~~~~~~~~~~~~~~
diff --git a/tests/ui/pinned_drop/conditional-drop-impl.rs b/tests/ui/pinned_drop/conditional-drop-impl.rs
new file mode 100644 (file)
index 0000000..23d756d
--- /dev/null
@@ -0,0 +1,27 @@
+use std::pin::Pin;
+
+use pin_project::{pin_project, pinned_drop};
+
+// In `Drop` impl, the implementor must specify the same requirement as type definition.
+
+struct DropImpl<T> {
+    f: T,
+}
+
+impl<T: Unpin> Drop for DropImpl<T> {
+    //~^ ERROR E0367
+    fn drop(&mut self) {}
+}
+
+#[pin_project(PinnedDrop)] //~ ERROR E0277
+struct PinnedDropImpl<T> {
+    #[pin]
+    f: T,
+}
+
+#[pinned_drop]
+impl<T: Unpin> PinnedDrop for PinnedDropImpl<T> {
+    fn drop(self: Pin<&mut Self>) {}
+}
+
+fn main() {}
diff --git a/tests/ui/pinned_drop/conditional-drop-impl.stderr b/tests/ui/pinned_drop/conditional-drop-impl.stderr
new file mode 100644 (file)
index 0000000..0587765
--- /dev/null
@@ -0,0 +1,28 @@
+error[E0367]: `Drop` impl requires `T: Unpin` but the struct it is implemented for does not
+  --> tests/ui/pinned_drop/conditional-drop-impl.rs:11:9
+   |
+11 | impl<T: Unpin> Drop for DropImpl<T> {
+   |         ^^^^^
+   |
+note: the implementor must specify the same requirement
+  --> tests/ui/pinned_drop/conditional-drop-impl.rs:7:1
+   |
+7  | struct DropImpl<T> {
+   | ^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `T` cannot be unpinned
+  --> tests/ui/pinned_drop/conditional-drop-impl.rs:16:15
+   |
+16 | #[pin_project(PinnedDrop)] //~ ERROR E0277
+   |               ^^^^^^^^^^ the trait `Unpin` is not implemented for `T`
+   |
+   = note: consider using `Box::pin`
+note: required because of the requirements on the impl of `PinnedDrop` for `PinnedDropImpl<T>`
+  --> tests/ui/pinned_drop/conditional-drop-impl.rs:23:16
+   |
+23 | impl<T: Unpin> PinnedDrop for PinnedDropImpl<T> {
+   |                ^^^^^^^^^^     ^^^^^^^^^^^^^^^^^
+help: consider restricting type parameter `T`
+   |
+17 | struct PinnedDropImpl<T: std::marker::Unpin> {
+   |                        ++++++++++++++++++++
diff --git a/tests/ui/pinned_drop/forget-pinned-drop-impl.rs b/tests/ui/pinned_drop/forget-pinned-drop-impl.rs
new file mode 100644 (file)
index 0000000..e31f46f
--- /dev/null
@@ -0,0 +1,9 @@
+use pin_project::pin_project;
+
+#[pin_project(PinnedDrop)] //~ ERROR E0277
+struct Struct {
+    #[pin]
+    f: u8,
+}
+
+fn main() {}
diff --git a/tests/ui/pinned_drop/forget-pinned-drop-impl.stderr b/tests/ui/pinned_drop/forget-pinned-drop-impl.stderr
new file mode 100644 (file)
index 0000000..ef8a7bf
--- /dev/null
@@ -0,0 +1,5 @@
+error[E0277]: the trait bound `Struct: PinnedDrop` is not satisfied
+ --> tests/ui/pinned_drop/forget-pinned-drop-impl.rs:3:15
+  |
+3 | #[pin_project(PinnedDrop)] //~ ERROR E0277
+  |               ^^^^^^^^^^ the trait `PinnedDrop` is not implemented for `Struct`
diff --git a/tests/ui/pinned_drop/invalid-self.rs b/tests/ui/pinned_drop/invalid-self.rs
new file mode 100644 (file)
index 0000000..783167f
--- /dev/null
@@ -0,0 +1,14 @@
+// by-ref binding `ref (mut) self` and sub-patterns `@` are not allowed in receivers (rejected by rustc).
+
+use std::pin::Pin;
+
+struct S {}
+
+impl S {
+    fn take_ref_self(ref self: Pin<&mut Self>) {} //~ ERROR expected identifier, found keyword `self`
+    fn take_ref_mut_self(ref mut self: Pin<&mut Self>) {} //~ ERROR expected identifier, found keyword `self`
+
+    fn self_subpat(self @ S {}: Self) {} //~ ERROR expected one of `)`, `,`, or `:`, found `@`
+}
+
+fn main() {}
diff --git a/tests/ui/pinned_drop/invalid-self.stderr b/tests/ui/pinned_drop/invalid-self.stderr
new file mode 100644 (file)
index 0000000..464be5e
--- /dev/null
@@ -0,0 +1,25 @@
+error: expected identifier, found keyword `self`
+ --> tests/ui/pinned_drop/invalid-self.rs:8:26
+  |
+8 |     fn take_ref_self(ref self: Pin<&mut Self>) {} //~ ERROR expected identifier, found keyword `self`
+  |                          ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `self`
+ --> tests/ui/pinned_drop/invalid-self.rs:9:34
+  |
+9 |     fn take_ref_mut_self(ref mut self: Pin<&mut Self>) {} //~ ERROR expected identifier, found keyword `self`
+  |                                  ^^^^ expected identifier, found keyword
+
+error: expected parameter name, found `@`
+  --> tests/ui/pinned_drop/invalid-self.rs:11:25
+   |
+11 |     fn self_subpat(self @ S {}: Self) {} //~ ERROR expected one of `)`, `,`, or `:`, found `@`
+   |                         ^ expected parameter name
+
+error: expected one of `)`, `,`, or `:`, found `@`
+  --> tests/ui/pinned_drop/invalid-self.rs:11:25
+   |
+11 |     fn self_subpat(self @ S {}: Self) {} //~ ERROR expected one of `)`, `,`, or `:`, found `@`
+   |                        -^ expected one of `)`, `,`, or `:`
+   |                        |
+   |                        help: missing `,`
diff --git a/tests/ui/pinned_drop/invalid.rs b/tests/ui/pinned_drop/invalid.rs
new file mode 100644 (file)
index 0000000..fdadf8a
--- /dev/null
@@ -0,0 +1,231 @@
+mod argument {
+    use std::pin::Pin;
+
+    use pin_project::{pin_project, pinned_drop};
+
+    #[pin_project(PinnedDrop)]
+    struct UnexpectedArg1(());
+
+    #[pinned_drop(foo)] //~ ERROR unexpected token
+    impl PinnedDrop for UnexpectedArg1 {
+        fn drop(self: Pin<&mut Self>) {}
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct UnexpectedArg2(());
+
+    #[pinned_drop()] // Ok
+    impl PinnedDrop for UnexpectedArg2 {
+        fn drop(self: Pin<&mut Self>) {}
+    }
+}
+
+mod attribute {
+    use pin_project::{pin_project, pinned_drop};
+
+    #[pin_project(PinnedDrop)]
+    struct Duplicate(());
+
+    #[pinned_drop]
+    #[pinned_drop] //~ ERROR duplicate #[pinned_drop] attribute
+    impl PinnedDrop for Duplicate {
+        fn drop(self: Pin<&mut Self>) {}
+    }
+}
+
+mod item {
+    use pin_project::{pin_project, pinned_drop};
+
+    #[pin_project(PinnedDrop)]
+    struct TraitImpl(());
+
+    #[pinned_drop]
+    impl Drop for TraitImpl {} //~ ERROR may only be used on implementation for the `PinnedDrop` trait
+
+    #[pin_project(PinnedDrop)]
+    struct InherentImpl(());
+
+    #[pinned_drop]
+    impl InherentImpl {} //~ ERROR may only be used on implementation for the `PinnedDrop` trait
+
+    #[pinned_drop]
+    fn func(_: Pin<&mut ()>) {} //~ ERROR expected `impl`
+}
+
+mod unsafety {
+    use pin_project::{pin_project, pinned_drop};
+
+    #[pin_project(PinnedDrop)]
+    struct Impl(());
+
+    #[pinned_drop]
+    unsafe impl PinnedDrop for Impl {
+        //~^ ERROR implementing the trait `PinnedDrop` is not unsafe
+        fn drop(self: Pin<&mut Self>) {}
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct Method(());
+
+    #[pinned_drop]
+    impl PinnedDrop for Method {
+        unsafe fn drop(self: Pin<&mut Self>) {} //~ ERROR implementing the method `drop` is not unsafe
+    }
+}
+
+mod assoc_item {
+    use pin_project::{pin_project, pinned_drop};
+
+    #[pin_project(PinnedDrop)]
+    struct Empty(());
+
+    #[pinned_drop]
+    impl PinnedDrop for Empty {} //~ ERROR not all trait items implemented, missing: `drop`
+
+    #[pin_project(PinnedDrop)]
+    struct Const1(());
+
+    #[pinned_drop]
+    impl PinnedDrop for Const1 {
+        const A: u8 = 0; //~ ERROR const `A` is not a member of trait `PinnedDrop`
+        fn drop(self: Pin<&mut Self>) {}
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct Const2(());
+
+    #[pinned_drop]
+    impl PinnedDrop for Const2 {
+        fn drop(self: Pin<&mut Self>) {}
+        const A: u8 = 0; //~ ERROR const `A` is not a member of trait `PinnedDrop`
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct Type1(());
+
+    #[pinned_drop]
+    impl PinnedDrop for Type1 {
+        type A = u8; //~ ERROR type `A` is not a member of trait `PinnedDrop`
+        fn drop(self: Pin<&mut Self>) {}
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct Type2(());
+
+    #[pinned_drop]
+    impl PinnedDrop for Type2 {
+        fn drop(self: Pin<&mut Self>) {}
+        type A = u8; //~ ERROR type `A` is not a member of trait `PinnedDrop`
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct Duplicate(());
+
+    #[pinned_drop]
+    impl PinnedDrop for Duplicate {
+        fn drop(self: Pin<&mut Self>) {}
+        fn drop(self: Pin<&mut Self>) {} //~ ERROR duplicate definitions with name `drop`
+    }
+}
+
+mod method {
+    use std::pin::Pin;
+
+    use pin_project::{pin_project, pinned_drop};
+
+    #[pin_project(PinnedDrop)]
+    struct RetUnit(());
+
+    #[pinned_drop]
+    impl PinnedDrop for RetUnit {
+        fn drop(self: Pin<&mut Self>) -> () {} // Ok
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct RetTy(());
+
+    #[pinned_drop]
+    impl PinnedDrop for RetTy {
+        fn drop(self: Pin<&mut Self>) -> Self {} //~ ERROR method `drop` must return the unit type
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct NoArg(());
+
+    #[pinned_drop]
+    impl PinnedDrop for NoArg {
+        fn drop() {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>`
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct MultiArg(());
+
+    #[pinned_drop]
+    impl PinnedDrop for MultiArg {
+        fn drop(self: Pin<&mut Self>, _: ()) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>`
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct InvalidArg1(());
+
+    #[pinned_drop]
+    impl PinnedDrop for InvalidArg1 {
+        fn drop(&mut self) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>`
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct InvalidArg2(());
+
+    #[pinned_drop]
+    impl PinnedDrop for InvalidArg2 {
+        fn drop(_: Pin<&mut Self>) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>`
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct InvalidArg3(());
+
+    #[pinned_drop]
+    impl PinnedDrop for InvalidArg3 {
+        fn drop(self: Pin<&Self>) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>`
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct InvalidArg4(());
+
+    #[pinned_drop]
+    impl PinnedDrop for InvalidArg4 {
+        fn drop(self: Pin<&mut ()>) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>`
+    }
+
+    #[pin_project(PinnedDrop)]
+    struct InvalidName(());
+
+    #[pinned_drop]
+    impl PinnedDrop for InvalidName {
+        fn pinned_drop(self: Pin<&mut Self>) {} //~ ERROR method `pinned_drop` is not a member of trait `PinnedDrop
+    }
+}
+
+mod self_ty {
+    use pin_project::pinned_drop;
+
+    #[pinned_drop]
+    impl PinnedDrop for () {
+        //~^ ERROR implementing the trait `PinnedDrop` on this type is unsupported
+        fn drop(self: Pin<&mut Self>) {}
+    }
+
+    #[pinned_drop]
+    impl PinnedDrop for &mut A {
+        //~^ ERROR implementing the trait `PinnedDrop` on this type is unsupported
+        fn drop(self: Pin<&mut Self>) {}
+    }
+
+    #[pinned_drop]
+    impl PinnedDrop for [A] {
+        //~^ ERROR implementing the trait `PinnedDrop` on this type is unsupported
+        fn drop(self: Pin<&mut Self>) {}
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/pinned_drop/invalid.stderr b/tests/ui/pinned_drop/invalid.stderr
new file mode 100644 (file)
index 0000000..d509964
--- /dev/null
@@ -0,0 +1,143 @@
+error: unexpected token: `foo`
+ --> tests/ui/pinned_drop/invalid.rs:9:19
+  |
+9 |     #[pinned_drop(foo)] //~ ERROR unexpected token
+  |                   ^^^
+
+error: duplicate #[pinned_drop] attribute
+  --> tests/ui/pinned_drop/invalid.rs:30:5
+   |
+30 |     #[pinned_drop] //~ ERROR duplicate #[pinned_drop] attribute
+   |     ^^^^^^^^^^^^^^
+
+error: #[pinned_drop] may only be used on implementation for the `PinnedDrop` trait
+  --> tests/ui/pinned_drop/invalid.rs:43:10
+   |
+43 |     impl Drop for TraitImpl {} //~ ERROR may only be used on implementation for the `PinnedDrop` trait
+   |          ^^^^
+
+error: #[pinned_drop] may only be used on implementation for the `PinnedDrop` trait
+  --> tests/ui/pinned_drop/invalid.rs:49:10
+   |
+49 |     impl InherentImpl {} //~ ERROR may only be used on implementation for the `PinnedDrop` trait
+   |          ^^^^^^^^^^^^
+
+error: expected `impl`
+  --> tests/ui/pinned_drop/invalid.rs:52:5
+   |
+52 |     fn func(_: Pin<&mut ()>) {} //~ ERROR expected `impl`
+   |     ^^
+
+error: implementing the trait `PinnedDrop` is not unsafe
+  --> tests/ui/pinned_drop/invalid.rs:62:5
+   |
+62 |     unsafe impl PinnedDrop for Impl {
+   |     ^^^^^^
+
+error: implementing the method `drop` is not unsafe
+  --> tests/ui/pinned_drop/invalid.rs:72:9
+   |
+72 |         unsafe fn drop(self: Pin<&mut Self>) {} //~ ERROR implementing the method `drop` is not unsafe
+   |         ^^^^^^
+
+error: not all trait items implemented, missing: `drop`
+  --> tests/ui/pinned_drop/invalid.rs:83:5
+   |
+83 |     impl PinnedDrop for Empty {} //~ ERROR not all trait items implemented, missing: `drop`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: const `A` is not a member of trait `PinnedDrop`
+  --> tests/ui/pinned_drop/invalid.rs:90:9
+   |
+90 |         const A: u8 = 0; //~ ERROR const `A` is not a member of trait `PinnedDrop`
+   |         ^^^^^^^^^^^^^^^^
+
+error: const `A` is not a member of trait `PinnedDrop`
+   --> tests/ui/pinned_drop/invalid.rs:100:9
+    |
+100 |         const A: u8 = 0; //~ ERROR const `A` is not a member of trait `PinnedDrop`
+    |         ^^^^^^^^^^^^^^^^
+
+error: type `A` is not a member of trait `PinnedDrop`
+   --> tests/ui/pinned_drop/invalid.rs:108:9
+    |
+108 |         type A = u8; //~ ERROR type `A` is not a member of trait `PinnedDrop`
+    |         ^^^^^^^^^^^^
+
+error: type `A` is not a member of trait `PinnedDrop`
+   --> tests/ui/pinned_drop/invalid.rs:118:9
+    |
+118 |         type A = u8; //~ ERROR type `A` is not a member of trait `PinnedDrop`
+    |         ^^^^^^^^^^^^
+
+error: duplicate definitions with name `drop`
+   --> tests/ui/pinned_drop/invalid.rs:127:9
+    |
+127 |         fn drop(self: Pin<&mut Self>) {} //~ ERROR duplicate definitions with name `drop`
+    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: method `drop` must return the unit type
+   --> tests/ui/pinned_drop/invalid.rs:149:42
+    |
+149 |         fn drop(self: Pin<&mut Self>) -> Self {} //~ ERROR method `drop` must return the unit type
+    |                                          ^^^^
+
+error: method `drop` must take an argument `self: Pin<&mut Self>`
+   --> tests/ui/pinned_drop/invalid.rs:157:16
+    |
+157 |         fn drop() {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>`
+    |                ^^
+
+error: method `drop` must take an argument `self: Pin<&mut Self>`
+   --> tests/ui/pinned_drop/invalid.rs:165:17
+    |
+165 |         fn drop(self: Pin<&mut Self>, _: ()) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>`
+    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: method `drop` must take an argument `self: Pin<&mut Self>`
+   --> tests/ui/pinned_drop/invalid.rs:173:17
+    |
+173 |         fn drop(&mut self) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>`
+    |                 ^^^^^^^^^
+
+error: method `drop` must take an argument `self: Pin<&mut Self>`
+   --> tests/ui/pinned_drop/invalid.rs:181:17
+    |
+181 |         fn drop(_: Pin<&mut Self>) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>`
+    |                 ^^^^^^^^^^^^^^^^^
+
+error: method `drop` must take an argument `self: Pin<&mut Self>`
+   --> tests/ui/pinned_drop/invalid.rs:189:17
+    |
+189 |         fn drop(self: Pin<&Self>) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>`
+    |                 ^^^^^^^^^^^^^^^^
+
+error: method `drop` must take an argument `self: Pin<&mut Self>`
+   --> tests/ui/pinned_drop/invalid.rs:197:17
+    |
+197 |         fn drop(self: Pin<&mut ()>) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>`
+    |                 ^^^^^^^^^^^^^^^^^^
+
+error: method `pinned_drop` is not a member of trait `PinnedDrop
+   --> tests/ui/pinned_drop/invalid.rs:205:12
+    |
+205 |         fn pinned_drop(self: Pin<&mut Self>) {} //~ ERROR method `pinned_drop` is not a member of trait `PinnedDrop
+    |            ^^^^^^^^^^^
+
+error: implementing the trait `PinnedDrop` on this type is unsupported
+   --> tests/ui/pinned_drop/invalid.rs:213:25
+    |
+213 |     impl PinnedDrop for () {
+    |                         ^^
+
+error: implementing the trait `PinnedDrop` on this type is unsupported
+   --> tests/ui/pinned_drop/invalid.rs:219:25
+    |
+219 |     impl PinnedDrop for &mut A {
+    |                         ^^^^^^
+
+error: implementing the trait `PinnedDrop` on this type is unsupported
+   --> tests/ui/pinned_drop/invalid.rs:225:25
+    |
+225 |     impl PinnedDrop for [A] {
+    |                         ^^^
diff --git a/tests/ui/pinned_drop/pinned-drop-no-attr-arg.rs b/tests/ui/pinned_drop/pinned-drop-no-attr-arg.rs
new file mode 100644 (file)
index 0000000..391f290
--- /dev/null
@@ -0,0 +1,17 @@
+use std::pin::Pin;
+
+use pin_project::{pin_project, pinned_drop};
+
+#[pin_project]
+struct S {
+    #[pin]
+    f: u8,
+}
+
+#[pinned_drop]
+impl PinnedDrop for S {
+    //~^ ERROR E0119
+    fn drop(self: Pin<&mut Self>) {}
+}
+
+fn main() {}
diff --git a/tests/ui/pinned_drop/pinned-drop-no-attr-arg.stderr b/tests/ui/pinned_drop/pinned-drop-no-attr-arg.stderr
new file mode 100644 (file)
index 0000000..2542254
--- /dev/null
@@ -0,0 +1,8 @@
+error[E0119]: conflicting implementations of trait `_::_pin_project::__private::PinnedDrop` for type `S`
+  --> tests/ui/pinned_drop/pinned-drop-no-attr-arg.rs:12:1
+   |
+5  | #[pin_project]
+   | -------------- first implementation here
+...
+12 | impl PinnedDrop for S {
+   | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S`
diff --git a/tests/ui/pinned_drop/self.rs b/tests/ui/pinned_drop/self.rs
new file mode 100644 (file)
index 0000000..ff63402
--- /dev/null
@@ -0,0 +1,58 @@
+pub mod self_in_macro_def {
+    use std::pin::Pin;
+
+    use pin_project::{pin_project, pinned_drop};
+
+    #[pin_project(PinnedDrop)]
+    pub struct S {
+        f: (),
+    }
+
+    #[pinned_drop]
+    impl PinnedDrop for S {
+        fn drop(self: Pin<&mut Self>) {
+            macro_rules! t {
+                () => {{
+                    let _ = self; //~ ERROR E0434
+
+                    fn f(self: ()) {} //~ ERROR `self` parameter is only allowed in associated functions
+                }};
+            }
+            t!();
+        }
+    }
+}
+
+pub mod self_span {
+    use std::pin::Pin;
+
+    use pin_project::{pin_project, pinned_drop};
+
+    #[pin_project(PinnedDrop)]
+    pub struct S {
+        f: (),
+    }
+
+    #[pinned_drop]
+    impl PinnedDrop for S {
+        fn drop(self: Pin<&mut Self>) {
+            let _: () = self; //~ ERROR E0308
+            let _: Self = Self; //~ ERROR E0423
+        }
+    }
+
+    #[pin_project(PinnedDrop)]
+    pub enum E {
+        V { f: () },
+    }
+
+    #[pinned_drop]
+    impl PinnedDrop for E {
+        fn drop(self: Pin<&mut Self>) {
+            let _: () = self; //~ ERROR E0308
+            let _: Self = Self::V; //~ ERROR E0533
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/pinned_drop/self.stderr b/tests/ui/pinned_drop/self.stderr
new file mode 100644 (file)
index 0000000..a19d5a0
--- /dev/null
@@ -0,0 +1,62 @@
+error: `self` parameter is only allowed in associated functions
+  --> tests/ui/pinned_drop/self.rs:18:26
+   |
+18 |                     fn f(self: ()) {} //~ ERROR `self` parameter is only allowed in associated functions
+   |                          ^^^^ not semantically valid as function parameter
+...
+21 |             t!();
+   |             ---- in this macro invocation
+   |
+   = note: associated functions are those in `impl` or `trait` definitions
+   = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0434]: can't capture dynamic environment in a fn item
+  --> tests/ui/pinned_drop/self.rs:16:29
+   |
+16 |                     let _ = self; //~ ERROR E0434
+   |                             ^^^^
+...
+21 |             t!();
+   |             ---- in this macro invocation
+   |
+   = help: use the `|| { ... }` closure form instead
+   = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0423]: expected value, found struct `S`
+  --> tests/ui/pinned_drop/self.rs:40:27
+   |
+32 | /     pub struct S {
+33 | |         f: (),
+34 | |     }
+   | |_____- `S` defined here
+...
+40 |               let _: Self = Self; //~ ERROR E0423
+   |                             ^^^^ help: use struct literal syntax instead: `S { f: val }`
+
+error[E0308]: mismatched types
+  --> tests/ui/pinned_drop/self.rs:39:25
+   |
+39 |             let _: () = self; //~ ERROR E0308
+   |                    --   ^^^^ expected `()`, found struct `Pin`
+   |                    |
+   |                    expected due to this
+   |
+   = note: expected unit type `()`
+                 found struct `Pin<&mut self_span::S>`
+
+error[E0308]: mismatched types
+  --> tests/ui/pinned_drop/self.rs:52:25
+   |
+52 |             let _: () = self; //~ ERROR E0308
+   |                    --   ^^^^ expected `()`, found struct `Pin`
+   |                    |
+   |                    expected due to this
+   |
+   = note: expected unit type `()`
+                 found struct `Pin<&mut E>`
+
+error[E0533]: expected unit struct, unit variant or constant, found struct variant `E::V`
+  --> tests/ui/pinned_drop/self.rs:53:27
+   |
+53 |             let _: Self = Self::V; //~ ERROR E0533
+   |                           ^^^^^^^
diff --git a/tests/ui/pinned_drop/unsafe-call.rs b/tests/ui/pinned_drop/unsafe-call.rs
new file mode 100644 (file)
index 0000000..3ee2b56
--- /dev/null
@@ -0,0 +1,18 @@
+use std::pin::Pin;
+
+use pin_project::{pin_project, pinned_drop};
+
+#[pin_project(PinnedDrop)]
+struct S {
+    #[pin]
+    f: u8,
+}
+
+#[pinned_drop]
+impl PinnedDrop for S {
+    fn drop(self: Pin<&mut Self>) {
+        self.project().f.get_unchecked_mut(); //~ ERROR call to unsafe function is unsafe and requires unsafe function or block [E0133]
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/pinned_drop/unsafe-call.stderr b/tests/ui/pinned_drop/unsafe-call.stderr
new file mode 100644 (file)
index 0000000..9f7dd44
--- /dev/null
@@ -0,0 +1,7 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> tests/ui/pinned_drop/unsafe-call.rs:14:9
+   |
+14 |         self.project().f.get_unchecked_mut(); //~ ERROR call to unsafe function is unsafe and requires unsafe function or block [E0133]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
diff --git a/tests/ui/unsafe_unpin/conflict-unpin.rs b/tests/ui/unsafe_unpin/conflict-unpin.rs
new file mode 100644 (file)
index 0000000..ac9d1f8
--- /dev/null
@@ -0,0 +1,30 @@
+use pin_project::pin_project;
+
+#[pin_project(UnsafeUnpin)] //~ ERROR E0119
+struct Foo<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+impl<T, U> Unpin for Foo<T, U> where T: Unpin {}
+
+#[pin_project(UnsafeUnpin)] //~ ERROR E0119
+struct Bar<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+impl<T, U> Unpin for Bar<T, U> {}
+
+#[pin_project(UnsafeUnpin)] //~ ERROR E0119
+struct Baz<T, U> {
+    #[pin]
+    f1: T,
+    f2: U,
+}
+
+impl<T: Unpin, U: Unpin> Unpin for Baz<T, U> {}
+
+fn main() {}
diff --git a/tests/ui/unsafe_unpin/conflict-unpin.stderr b/tests/ui/unsafe_unpin/conflict-unpin.stderr
new file mode 100644 (file)
index 0000000..0e89b03
--- /dev/null
@@ -0,0 +1,32 @@
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Foo<_, _>`
+  --> tests/ui/unsafe_unpin/conflict-unpin.rs:3:15
+   |
+3  | #[pin_project(UnsafeUnpin)] //~ ERROR E0119
+   |               ^^^^^^^^^^^ conflicting implementation for `Foo<_, _>`
+...
+10 | impl<T, U> Unpin for Foo<T, U> where T: Unpin {}
+   | ------------------------------ first implementation here
+   |
+   = note: upstream crates may add a new impl of trait `_::_pin_project::UnsafeUnpin` for type `_::_pin_project::__private::Wrapper<'_, Foo<_, _>>` in future versions
+
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Bar<_, _>`
+  --> tests/ui/unsafe_unpin/conflict-unpin.rs:12:15
+   |
+12 | #[pin_project(UnsafeUnpin)] //~ ERROR E0119
+   |               ^^^^^^^^^^^ conflicting implementation for `Bar<_, _>`
+...
+19 | impl<T, U> Unpin for Bar<T, U> {}
+   | ------------------------------ first implementation here
+   |
+   = note: upstream crates may add a new impl of trait `_::_pin_project::UnsafeUnpin` for type `_::_pin_project::__private::Wrapper<'_, Bar<_, _>>` in future versions
+
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Baz<_, _>`
+  --> tests/ui/unsafe_unpin/conflict-unpin.rs:21:15
+   |
+21 | #[pin_project(UnsafeUnpin)] //~ ERROR E0119
+   |               ^^^^^^^^^^^ conflicting implementation for `Baz<_, _>`
+...
+28 | impl<T: Unpin, U: Unpin> Unpin for Baz<T, U> {}
+   | -------------------------------------------- first implementation here
+   |
+   = note: upstream crates may add a new impl of trait `_::_pin_project::UnsafeUnpin` for type `_::_pin_project::__private::Wrapper<'_, Baz<_, _>>` in future versions
diff --git a/tests/ui/unstable-features/README.md b/tests/ui/unstable-features/README.md
new file mode 100644 (file)
index 0000000..96f370c
--- /dev/null
@@ -0,0 +1,7 @@
+# UI tests for unstable features
+
+These tests check how the guarantees and features provided by pin-project
+interact with unstable language features.
+
+The names of the files contained in this directory need to begin with the name
+of the feature.
diff --git a/tests/ui/unstable-features/marker_trait_attr-feature-gate.rs b/tests/ui/unstable-features/marker_trait_attr-feature-gate.rs
new file mode 100644 (file)
index 0000000..542250b
--- /dev/null
@@ -0,0 +1,20 @@
+// Note: If you change this test, change 'marker_trait_attr.rs' at the same time.
+
+use std::marker::PhantomPinned;
+
+use pin_project::pin_project;
+
+#[pin_project] //~ ERROR E0119
+struct Struct<T> {
+    #[pin]
+    f: T,
+}
+
+// unsound Unpin impl
+impl<T> Unpin for Struct<T> {}
+
+fn is_unpin<T: Unpin>() {}
+
+fn main() {
+    is_unpin::<Struct<PhantomPinned>>()
+}
diff --git a/tests/ui/unstable-features/marker_trait_attr-feature-gate.stderr b/tests/ui/unstable-features/marker_trait_attr-feature-gate.stderr
new file mode 100644 (file)
index 0000000..3412f2e
--- /dev/null
@@ -0,0 +1,10 @@
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Struct<_>`
+  --> tests/ui/unstable-features/marker_trait_attr-feature-gate.rs:7:1
+   |
+7  | #[pin_project] //~ ERROR E0119
+   | ^^^^^^^^^^^^^^ conflicting implementation for `Struct<_>`
+...
+14 | impl<T> Unpin for Struct<T> {}
+   | --------------------------- first implementation here
+   |
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/unstable-features/marker_trait_attr.rs b/tests/ui/unstable-features/marker_trait_attr.rs
new file mode 100644 (file)
index 0000000..9c8e664
--- /dev/null
@@ -0,0 +1,26 @@
+// Note: If you change this test, change 'marker_trait_attr-feature-gate.rs' at the same time.
+
+// marker_trait_attr
+// Tracking issue: https://github.com/rust-lang/rust/issues/29864
+#![feature(marker_trait_attr)]
+
+// See https://github.com/taiki-e/pin-project/issues/105#issuecomment-535355974
+
+use std::marker::PhantomPinned;
+
+use pin_project::pin_project;
+
+#[pin_project] //~ ERROR E0119
+struct Struct<T> {
+    #[pin]
+    f: T,
+}
+
+// unsound Unpin impl
+impl<T> Unpin for Struct<T> {}
+
+fn is_unpin<T: Unpin>() {}
+
+fn main() {
+    is_unpin::<Struct<PhantomPinned>>()
+}
diff --git a/tests/ui/unstable-features/marker_trait_attr.stderr b/tests/ui/unstable-features/marker_trait_attr.stderr
new file mode 100644 (file)
index 0000000..2b68c80
--- /dev/null
@@ -0,0 +1,10 @@
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Struct<_>`
+  --> tests/ui/unstable-features/marker_trait_attr.rs:13:1
+   |
+13 | #[pin_project] //~ ERROR E0119
+   | ^^^^^^^^^^^^^^ conflicting implementation for `Struct<_>`
+...
+20 | impl<T> Unpin for Struct<T> {}
+   | --------------------------- first implementation here
+   |
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/unstable-features/negative_impls.rs b/tests/ui/unstable-features/negative_impls.rs
new file mode 100644 (file)
index 0000000..9605642
--- /dev/null
@@ -0,0 +1,23 @@
+#![feature(negative_impls)]
+#![deny(suspicious_auto_trait_impls)]
+
+// https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/design.20meeting.3A.20backlog.20bonanza/near/269471299
+// https://github.com/taiki-e/pin-project/issues/340
+
+#[pin_project::pin_project]
+struct Foo<Pinned, Unpinned> {
+    #[pin]
+    pinned: Pinned,
+
+    unpinned: Unpinned,
+}
+
+struct MyPhantomPinned {}
+impl !Unpin for MyPhantomPinned {}
+impl Unpin for Foo<MyPhantomPinned, ()> {}
+
+fn is_unpin<T: Unpin>() {}
+
+fn main() {
+    is_unpin::<Foo<MyPhantomPinned, ()>>()
+}
diff --git a/tests/ui/unstable-features/negative_impls.stderr b/tests/ui/unstable-features/negative_impls.stderr
new file mode 100644 (file)
index 0000000..0d99e2b
--- /dev/null
@@ -0,0 +1,19 @@
+error: cross-crate traits with a default impl, like `Unpin`, should not be specialized
+  --> tests/ui/unstable-features/negative_impls.rs:17:1
+   |
+17 | impl Unpin for Foo<MyPhantomPinned, ()> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> tests/ui/unstable-features/negative_impls.rs:2:9
+   |
+2  | #![deny(suspicious_auto_trait_impls)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367>
+   = note: `MyPhantomPinned` is not a generic parameter
+note: try using the same sequence of generic parameters as the struct definition
+  --> tests/ui/unstable-features/negative_impls.rs:8:1
+   |
+8  | struct Foo<Pinned, Unpinned> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/unstable-features/overlapping_marker_traits-feature-gate.rs b/tests/ui/unstable-features/overlapping_marker_traits-feature-gate.rs
new file mode 100644 (file)
index 0000000..012c870
--- /dev/null
@@ -0,0 +1,20 @@
+// Note: If you change this test, change 'overlapping_marker_traits.rs' at the same time.
+
+use std::marker::PhantomPinned;
+
+use pin_project::pin_project;
+
+#[pin_project] //~ ERROR E0119
+struct Struct<T> {
+    #[pin]
+    f: T,
+}
+
+// unsound Unpin impl
+impl<T> Unpin for Struct<T> {}
+
+fn is_unpin<T: Unpin>() {}
+
+fn main() {
+    is_unpin::<Struct<PhantomPinned>>()
+}
diff --git a/tests/ui/unstable-features/overlapping_marker_traits-feature-gate.stderr b/tests/ui/unstable-features/overlapping_marker_traits-feature-gate.stderr
new file mode 100644 (file)
index 0000000..918d804
--- /dev/null
@@ -0,0 +1,10 @@
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Struct<_>`
+  --> tests/ui/unstable-features/overlapping_marker_traits-feature-gate.rs:7:1
+   |
+7  | #[pin_project] //~ ERROR E0119
+   | ^^^^^^^^^^^^^^ conflicting implementation for `Struct<_>`
+...
+14 | impl<T> Unpin for Struct<T> {}
+   | --------------------------- first implementation here
+   |
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/unstable-features/overlapping_marker_traits.rs b/tests/ui/unstable-features/overlapping_marker_traits.rs
new file mode 100644 (file)
index 0000000..8dc27c1
--- /dev/null
@@ -0,0 +1,30 @@
+// Note: If you change this test, change 'overlapping_marker_traits-feature-gate.rs' at the same time.
+
+// This feature could break the guarantee for Unpin provided by pin-project,
+// but was removed in https://github.com/rust-lang/rust/pull/68544 (nightly-2020-02-06).
+// Refs:
+// - https://github.com/rust-lang/rust/issues/29864#issuecomment-515780867
+// - https://github.com/taiki-e/pin-project/issues/105
+
+// overlapping_marker_traits
+// Tracking issue: https://github.com/rust-lang/rust/issues/29864
+#![feature(overlapping_marker_traits)]
+
+use std::marker::PhantomPinned;
+
+use pin_project::pin_project;
+
+#[pin_project]
+struct Struct<T> {
+    #[pin]
+    f: T,
+}
+
+// unsound Unpin impl
+impl<T> Unpin for Struct<T> {}
+
+fn is_unpin<T: Unpin>() {}
+
+fn main() {
+    is_unpin::<Struct<PhantomPinned>>()
+}
diff --git a/tests/ui/unstable-features/overlapping_marker_traits.stderr b/tests/ui/unstable-features/overlapping_marker_traits.stderr
new file mode 100644 (file)
index 0000000..3e8411d
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0557]: feature has been removed
+  --> tests/ui/unstable-features/overlapping_marker_traits.rs:11:12
+   |
+11 | #![feature(overlapping_marker_traits)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^ feature has been removed
+   |
+   = note: removed in favor of `#![feature(marker_trait_attr)]`
+
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Struct<_>`
+  --> tests/ui/unstable-features/overlapping_marker_traits.rs:17:1
+   |
+17 | #[pin_project]
+   | ^^^^^^^^^^^^^^ conflicting implementation for `Struct<_>`
+...
+24 | impl<T> Unpin for Struct<T> {}
+   | --------------------------- first implementation here
+   |
+   = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/unstable-features/trivial_bounds-feature-gate.rs b/tests/ui/unstable-features/trivial_bounds-feature-gate.rs
new file mode 100644 (file)
index 0000000..f8467b0
--- /dev/null
@@ -0,0 +1,53 @@
+// Note: If you change this test, change 'trivial_bounds.rs' at the same time.
+
+mod phantom_pinned {
+    use std::marker::{PhantomData, PhantomPinned};
+
+    struct A(PhantomPinned);
+
+    impl Unpin for A where PhantomPinned: Unpin {} //~ ERROR E0277
+
+    struct Wrapper<T>(T);
+
+    impl<T> Unpin for Wrapper<T> where T: Unpin {}
+
+    struct B(PhantomPinned);
+
+    impl Unpin for B where Wrapper<PhantomPinned>: Unpin {} //~ ERROR E0277
+
+    struct WrapperWithLifetime<'a, T>(PhantomData<&'a ()>, T);
+
+    impl<T> Unpin for WrapperWithLifetime<'_, T> where T: Unpin {}
+
+    struct C(PhantomPinned);
+
+    impl<'a> Unpin for C where WrapperWithLifetime<'a, PhantomPinned>: Unpin {} // Ok
+}
+
+mod inner {
+    use std::marker::{PhantomData, PhantomPinned};
+
+    struct Inner(PhantomPinned);
+
+    struct A(Inner);
+
+    impl Unpin for A where Inner: Unpin {} //~ ERROR E0277
+
+    struct Wrapper<T>(T);
+
+    impl<T> Unpin for Wrapper<T> where T: Unpin {}
+
+    struct B(Inner);
+
+    impl Unpin for B where Wrapper<Inner>: Unpin {} //~ ERROR E0277
+
+    struct WrapperWithLifetime<'a, T>(PhantomData<&'a ()>, T);
+
+    impl<T> Unpin for WrapperWithLifetime<'_, T> where T: Unpin {}
+
+    struct C(Inner);
+
+    impl<'a> Unpin for C where WrapperWithLifetime<'a, Inner>: Unpin {} // Ok
+}
+
+fn main() {}
diff --git a/tests/ui/unstable-features/trivial_bounds-feature-gate.stderr b/tests/ui/unstable-features/trivial_bounds-feature-gate.stderr
new file mode 100644 (file)
index 0000000..2e31658
--- /dev/null
@@ -0,0 +1,59 @@
+error[E0277]: `PhantomPinned` cannot be unpinned
+ --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:8:28
+  |
+8 |     impl Unpin for A where PhantomPinned: Unpin {} //~ ERROR E0277
+  |                            ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `PhantomPinned`
+  |
+  = note: consider using `Box::pin`
+  = help: see issue #48214
+  = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+
+error[E0277]: `PhantomPinned` cannot be unpinned
+  --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:16:28
+   |
+16 |     impl Unpin for B where Wrapper<PhantomPinned>: Unpin {} //~ ERROR E0277
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `PhantomPinned`
+   |
+   = note: consider using `Box::pin`
+note: required because of the requirements on the impl of `Unpin` for `phantom_pinned::Wrapper<PhantomPinned>`
+  --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:12:13
+   |
+12 |     impl<T> Unpin for Wrapper<T> where T: Unpin {}
+   |             ^^^^^     ^^^^^^^^^^
+   = help: see issue #48214
+   = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+
+error[E0277]: `PhantomPinned` cannot be unpinned
+  --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:34:28
+   |
+34 |     impl Unpin for A where Inner: Unpin {} //~ ERROR E0277
+   |                            ^^^^^^^^^^^^ within `Inner`, the trait `Unpin` is not implemented for `PhantomPinned`
+   |
+   = note: consider using `Box::pin`
+note: required because it appears within the type `Inner`
+  --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:30:12
+   |
+30 |     struct Inner(PhantomPinned);
+   |            ^^^^^
+   = help: see issue #48214
+   = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+
+error[E0277]: `PhantomPinned` cannot be unpinned
+  --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:42:28
+   |
+42 |     impl Unpin for B where Wrapper<Inner>: Unpin {} //~ ERROR E0277
+   |                            ^^^^^^^^^^^^^^^^^^^^^ within `Inner`, the trait `Unpin` is not implemented for `PhantomPinned`
+   |
+   = note: consider using `Box::pin`
+note: required because it appears within the type `Inner`
+  --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:30:12
+   |
+30 |     struct Inner(PhantomPinned);
+   |            ^^^^^
+note: required because of the requirements on the impl of `Unpin` for `inner::Wrapper<Inner>`
+  --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:38:13
+   |
+38 |     impl<T> Unpin for Wrapper<T> where T: Unpin {}
+   |             ^^^^^     ^^^^^^^^^^
+   = help: see issue #48214
+   = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
diff --git a/tests/ui/unstable-features/trivial_bounds.rs b/tests/ui/unstable-features/trivial_bounds.rs
new file mode 100644 (file)
index 0000000..41f885d
--- /dev/null
@@ -0,0 +1,38 @@
+// Note: If you change this test, change 'trivial_bounds-feature-gate.rs' at the same time.
+
+// trivial_bounds
+// Tracking issue: https://github.com/rust-lang/rust/issues/48214
+#![feature(trivial_bounds)]
+#![deny(trivial_bounds)]
+
+use std::marker::{PhantomData, PhantomPinned};
+
+fn inner() {
+    struct Inner(PhantomPinned);
+
+    struct A(PhantomPinned);
+
+    impl Unpin for A where PhantomPinned: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters
+
+    struct B(Inner);
+
+    impl Unpin for B where Inner: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters
+
+    struct Wrapper<T>(T);
+
+    impl<T> Unpin for Wrapper<T> where T: Unpin {}
+
+    struct C(Inner);
+
+    impl Unpin for C where Wrapper<Inner>: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters
+
+    struct WrapperWithLifetime<'a, T>(PhantomData<&'a ()>, T);
+
+    impl<T> Unpin for WrapperWithLifetime<'_, T> where T: Unpin {}
+
+    struct D(Inner);
+
+    impl<'a> Unpin for D where WrapperWithLifetime<'a, Inner>: Unpin {} // Ok
+}
+
+fn main() {}
diff --git a/tests/ui/unstable-features/trivial_bounds.stderr b/tests/ui/unstable-features/trivial_bounds.stderr
new file mode 100644 (file)
index 0000000..23f45c7
--- /dev/null
@@ -0,0 +1,23 @@
+error: trait bound PhantomPinned: Unpin does not depend on any type or lifetime parameters
+  --> tests/ui/unstable-features/trivial_bounds.rs:15:43
+   |
+15 |     impl Unpin for A where PhantomPinned: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters
+   |                                           ^^^^^
+   |
+note: the lint level is defined here
+  --> tests/ui/unstable-features/trivial_bounds.rs:6:9
+   |
+6  | #![deny(trivial_bounds)]
+   |         ^^^^^^^^^^^^^^
+
+error: trait bound Inner: Unpin does not depend on any type or lifetime parameters
+  --> tests/ui/unstable-features/trivial_bounds.rs:19:35
+   |
+19 |     impl Unpin for B where Inner: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters
+   |                                   ^^^^^
+
+error: trait bound Wrapper<Inner>: Unpin does not depend on any type or lifetime parameters
+  --> tests/ui/unstable-features/trivial_bounds.rs:27:44
+   |
+27 |     impl Unpin for C where Wrapper<Inner>: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters
+   |                                            ^^^^^
diff --git a/tests/unsafe_unpin.rs b/tests/unsafe_unpin.rs
new file mode 100644 (file)
index 0000000..8b6411c
--- /dev/null
@@ -0,0 +1,50 @@
+#![warn(rust_2018_idioms, single_use_lifetimes)]
+#![allow(dead_code)]
+
+#[macro_use]
+mod auxiliary;
+
+use std::marker::PhantomPinned;
+
+use pin_project::{pin_project, UnsafeUnpin};
+
+#[pin_project(UnsafeUnpin)]
+pub struct Blah<T, U> {
+    f1: U,
+    #[pin]
+    f2: T,
+}
+
+unsafe impl<T: Unpin, U> UnsafeUnpin for Blah<T, U> {}
+
+assert_unpin!(Blah<(), ()>);
+assert_unpin!(Blah<(), PhantomPinned>);
+assert_not_unpin!(Blah<PhantomPinned, ()>);
+assert_not_unpin!(Blah<PhantomPinned, PhantomPinned>);
+
+#[pin_project(UnsafeUnpin)]
+struct OverlappingLifetimeNames<'pin, T, U> {
+    #[pin]
+    f1: U,
+    #[pin]
+    f2: Option<T>,
+    f3: &'pin (),
+}
+
+unsafe impl<T: Unpin, U: Unpin> UnsafeUnpin for OverlappingLifetimeNames<'_, T, U> {}
+
+assert_unpin!(OverlappingLifetimeNames<'_, (), ()>);
+assert_not_unpin!(OverlappingLifetimeNames<'_, PhantomPinned, ()>);
+assert_not_unpin!(OverlappingLifetimeNames<'_, (), PhantomPinned>);
+assert_not_unpin!(OverlappingLifetimeNames<'_, PhantomPinned, PhantomPinned>);
+
+#[test]
+fn trivial_bounds() {
+    #[pin_project(UnsafeUnpin)]
+    pub struct NotImplementUnsafUnpin {
+        #[pin]
+        f: PhantomPinned,
+    }
+
+    assert_not_unpin!(NotImplementUnsafUnpin);
+}