Snap for 7183507 from 798e77f9ad5a4fd5b91b5cdf19ad52b515818522 to sdk-release

Change-Id: Idd508611509d15ace278060101b6d52a8aa27916
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 3ee260d..68cf6e8 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
 {
   "git": {
-    "sha1": "eaebdd63756a9eb509be14d601f85293ab78a95c"
+    "sha1": "5707cf226c74b81387f498bb5d6896d978fccd4a"
   }
 }
diff --git a/.clippy.toml b/.clippy.toml
deleted file mode 100644
index 983eb57..0000000
--- a/.clippy.toml
+++ /dev/null
@@ -1 +0,0 @@
-msrv = "1.37"
diff --git a/.editorconfig b/.editorconfig
deleted file mode 100644
index a73a88d..0000000
--- a/.editorconfig
+++ /dev/null
@@ -1,20 +0,0 @@
-# EditorConfig configuration
-# https://editorconfig.org
-
-root = true
-
-[*]
-charset = utf-8
-end_of_line = lf
-indent_size = 4
-indent_style = space
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-[*.{json,yml,md}]
-indent_size = 2
-
-[*.sh]
-indent_size = 2
-binary_next_line = true
-switch_case_indent = true
diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index 6313b56..0000000
--- a/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-* text=auto eol=lf
diff --git a/.rustfmt.toml b/.rustfmt.toml
deleted file mode 100644
index 6604f5c..0000000
--- a/.rustfmt.toml
+++ /dev/null
@@ -1,34 +0,0 @@
-# Rustfmt configuration
-# https://github.com/rust-lang/rustfmt/blob/HEAD/Configurations.md
-
-# This is required for bug-fixes, which technically can't be made to the stable
-# first version.
-# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3383).
-version = "Two"
-# Rustfmt cannot format long lines inside macros, but this option detects this.
-# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3391)
-error_on_line_overflow = true
-
-# Override the default formatting style.
-# See https://internals.rust-lang.org/t/running-rustfmt-on-rust-lang-rust-and-other-rust-lang-repositories/8732/81.
-use_small_heuristics = "Max"
-# See https://github.com/rust-dev-tools/fmt-rfcs/issues/149.
-# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3370)
-overflow_delimited_expr = true
-
-# Apply rustfmt to more places.
-# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3362).
-merge_imports = true
-# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3348).
-format_code_in_doc_comments = true
-
-# Automatically fix deprecated style.
-use_field_init_shorthand = true
-use_try_shorthand = true
-
-# Set the default settings again to always apply the proper formatting without
-# being affected by the editor settings.
-edition = "2018"
-hard_tabs = false
-newline_style = "Unix"
-tab_spaces = 4
diff --git a/Android.bp b/Android.bp
index b549a77..951c3ce 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,5 +1,41 @@
 // This file is generated by cargo2android.py --run --dependencies --device --patch=patches/Android.bp.patch.
 
+package {
+    default_applicable_licenses: ["external_rust_crates_pin-project_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+//
+// large-scale-change included anything that looked like it might be a license
+// text as a license_text. e.g. LICENSE, NOTICE, COPYING etc.
+//
+// Please consider removing redundant or irrelevant files from 'license_text:'.
+// See: http://go/android-license-faq
+license {
+    name: "external_rust_crates_pin-project_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-MIT",
+    ],
+    license_text: [
+        "LICENSE-APACHE",
+        "LICENSE-MIT",
+    ],
+}
+
 rust_library {
     name: "libpin_project",
     host_supported: true,
@@ -14,8 +50,8 @@
 }
 
 // dependent_library ["feature_list"]
-//   pin-project-internal-1.0.3
+//   pin-project-internal-1.0.5
 //   proc-macro2-1.0.24 "default,proc-macro"
 //   quote-1.0.8 "default,proc-macro"
-//   syn-1.0.58 "clone-impls,default,derive,full,parsing,printing,proc-macro,quote,visit,visit-mut"
+//   syn-1.0.60 "clone-impls,default,derive,full,parsing,printing,proc-macro,quote,visit-mut"
 //   unicode-xid-0.2.1 "default"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6551813..a36fdc6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,14 @@
 
 ## [Unreleased]
 
+## [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.
@@ -57,7 +65,7 @@
 
 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)
+- [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
 
@@ -100,26 +108,24 @@
 
 ## [0.4.26] - 2020-10-04
 
-- [Fix drop order of pinned fields in project_replace](https://github.com/taiki-e/pin-project/pull/287)
+- [Fix drop order of pinned fields in `project_replace`.](https://github.com/taiki-e/pin-project/pull/287)
 
 ## [0.4.25] - 2020-10-01
 
-- Suppress `drop_bounds` lint, which will be added to rustc in the future. See [#272](https://github.com/taiki-e/pin-project/issues/272) for more details.
+- [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
 
-- Fix compatibility of generated code with `forbid(future_incompatible)`
+- [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
 
-- [Fix compile error with `?Sized` type parameters.][263]
-
-[263]: https://github.com/taiki-e/pin-project/pull/263
+- [Fix compile error with `?Sized` type parameters.](https://github.com/taiki-e/pin-project/pull/263)
 
 ## [0.4.22] - 2020-06-14
 
@@ -127,7 +133,7 @@
 
 ## [0.4.21] - 2020-06-13
 
-- [Deprecated `#[project]`, `#[project_ref]`, and `#[project_replace]` attributes due to some unfixable limitations.][244]
+- [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.
 
@@ -146,22 +152,17 @@
   }
   ```
 
-  See [#225][225] for more details.
+  See [#225](https://github.com/taiki-e/pin-project/pull/225) for more details.
 
-- [Support `Self` in fields and generics in type definitions.][245]
+- [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.][250]
+- [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.
 
-[225]: https://github.com/taiki-e/pin-project/pull/225
-[244]: https://github.com/taiki-e/pin-project/pull/244
-[245]: https://github.com/taiki-e/pin-project/pull/245
-[250]: https://github.com/taiki-e/pin-project/pull/250
-
 ## [0.4.20] - 2020-06-07
 
-- [You can now use project_replace argument without Replace argument.][243]
+- [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
@@ -172,7 +173,7 @@
     }
   ```
 
-- [Makes `project_replace` argument an alias for `Replace` argument so that it can be used without a value.][243]
+- [Makes `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)]
@@ -183,32 +184,25 @@
 
   *The `Replace` argument will be deprecated in the future.*
 
-- Suppress `unreachable_pub` lint in generated code.
-
-[243]: https://github.com/taiki-e/pin-project/pull/243
+- [Suppress `unreachable_pub` lint in generated code.](https://github.com/taiki-e/pin-project/pull/240)
 
 ## [0.4.19] - 2020-06-04
 
-- [Fix `unused_results` lint in generated code.][239]
-
-[239]: https://github.com/taiki-e/pin-project/pull/239
+- [Suppress `unused_results` lint in generated code.](https://github.com/taiki-e/pin-project/pull/239)
 
 ## [0.4.18] - 2020-06-04
 
-- [Support `Self` in more syntax positions inside `#[pinned_drop]` impl.][230]
+- [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.][233]
+- [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.
 
-[230]: https://github.com/taiki-e/pin-project/pull/230
-[233]: https://github.com/taiki-e/pin-project/pull/233
-
 ## [0.4.17] - 2020-05-18
 
-- [Support naming the projection types.][202]
+- [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:
 
@@ -227,23 +221,17 @@
   }
   ```
 
-[202]: https://github.com/taiki-e/pin-project/pull/202
-
 ## [0.4.16] - 2020-05-11
 
-- [Fixed an issue that users can call internal function generated by `#[pinned_drop]`.][223]
-
-[223]: https://github.com/taiki-e/pin-project/pull/223
+- [Fixed 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
 
-- [`#[project]` attribute can now handle all project\* attributes in that scope with one wrapper attribute.][220]
-
-[220]: https://github.com/taiki-e/pin-project/pull/220
+- [`#[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
 
-- [Added `!Unpin` option to `#[pin_project]` attribute for guarantee the type is `!Unpin`.][219]
+- [Added `!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)]
@@ -265,218 +253,167 @@
 
   *[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)*
 
-- [Fixed an issue where duplicate `#[project]` attributes were ignored.][218]
+- [Fixed 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.][217]
+- [Suppress `single_use_lifetimes` lint in generated code.](https://github.com/taiki-e/pin-project/pull/217)
 
-- [Support overlapping lifetime names in HRTB.][217]
+- [Support overlapping lifetime names in HRTB.](https://github.com/taiki-e/pin-project/pull/217)
 
-- [Hide generated items from --document-private-items.][211] See [#211][211] for details.
+- [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.
 
-[211]: https://github.com/taiki-e/pin-project/pull/211
-[217]: https://github.com/taiki-e/pin-project/pull/217
-[218]: https://github.com/taiki-e/pin-project/pull/218
-[219]: https://github.com/taiki-e/pin-project/pull/219
-
 ## [0.4.13] - 2020-05-07
 
-- [Fixed a regression in 0.4.11.][207]
+- [Fixed 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):
 
-  - [Fixed an issue that `#[project]` on non-statement expression does not work without unstable features.][197]
+  - [Fixed 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.][199]
+  - [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]`.][200]
+  - [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.
 
-[207]: https://github.com/taiki-e/pin-project/pull/207
-
 ## [0.4.12] - 2020-05-07
 
-- A release to avoid [a regression in 0.4.11][206]. No code changes from [0.4.10](https://github.com/taiki-e/pin-project/releases/tag/v0.4.10).
-
-[206]: https://github.com/taiki-e/pin-project/issues/206
+- 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][206] for details.
+**Note: This release has been yanked.** See [#206](https://github.com/taiki-e/pin-project/issues/206) for details.
 
-- [Fixed an issue that `#[project]` on non-statement expression does not work without unstable features.][197]
+- [Fixed 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.][199]
+- [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]`.][200]
+- [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.
 
-[197]: https://github.com/taiki-e/pin-project/pull/197
-[199]: https://github.com/taiki-e/pin-project/pull/199
-[200]: https://github.com/taiki-e/pin-project/pull/200
-
 ## [0.4.10] - 2020-05-04
 
-- [Added `project_replace` method and `#[project_replace]` attribute.][194]
+- [Added `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.][190]
+- [Support `Self` and `self` in more syntax positions inside `#[pinned_drop]` impl.](https://github.com/taiki-e/pin-project/pull/190)
 
-- [Hided all generated items except for projected types from calling code.][192] See [#192][192] for details.
-
-[190]: https://github.com/taiki-e/pin-project/pull/190
-[192]: https://github.com/taiki-e/pin-project/pull/192
-[194]: https://github.com/taiki-e/pin-project/pull/194
+- [Hided 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
 
-- [Fixed lifetime inference error when associated types are used in fields.][188]
+- [Fixed lifetime inference error when associated types are used in fields.](https://github.com/taiki-e/pin-project/pull/188)
 
-- [Fixed compile error with tuple structs with `where` clauses.][186]
+- [Fixed 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.][181]
-
-[181]: https://github.com/taiki-e/pin-project/pull/181
-[186]: https://github.com/taiki-e/pin-project/pull/186
-[188]: https://github.com/taiki-e/pin-project/pull/188
+- [`#[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
 
-- [Ensured that users cannot implement `PinnedDrop` without proper attribute argument.][180]
+- [Ensured that users cannot implement `PinnedDrop` without proper attribute argument.](https://github.com/taiki-e/pin-project/pull/180)
 
-- [Fixed use of `Self` in expression position inside `#[pinned_drop]` impl.][177]
-
-[177]: https://github.com/taiki-e/pin-project/pull/180
-[180]: https://github.com/taiki-e/pin-project/pull/180
+- [Fixed 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
 
-- [Fixed support for lifetime bounds.][176]
-
-[176]: https://github.com/taiki-e/pin-project/pull/176
+- [Fixed support for lifetime bounds.](https://github.com/taiki-e/pin-project/pull/176)
 
 ## [0.4.6] - 2019-11-20
 
-- [Fixed compile error when there is `Self` in the where clause.][169]
-
-[169]: https://github.com/taiki-e/pin-project/pull/169
+- [Fixed 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
 
-- [Fixed compile error with `dyn` types.][158]
-
-[158]: https://github.com/taiki-e/pin-project/pull/158
+- [Fixed compile error with `dyn` types.](https://github.com/taiki-e/pin-project/pull/158)
 
 ## [0.4.4] - 2019-10-17
 
-- [Fixed an issue where `PinnedDrop` implementations can call unsafe code without an unsafe block.][149]
-
-[149]: https://github.com/taiki-e/pin-project/pull/149
+- [Fixed 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] for details.
+**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()]`.][135]
+- [`#[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.][135]
+- [`#[pin_project]` can now interoperate with `#[cfg()]` on tuple structs and tuple variants.](https://github.com/taiki-e/pin-project/pull/135)
 
-- [Fixed support for DSTs(Dynamically Sized Types) on `#[pin_project(UnsafeUnpin)]`][120]
+- [Fixed support for DSTs(Dynamically Sized Types) on `#[pin_project(UnsafeUnpin)]`](https://github.com/taiki-e/pin-project/pull/120)
 
 - Diagnostic improvements.
 
-[#148]: https://github.com/taiki-e/pin-project/pull/148
-[120]: https://github.com/taiki-e/pin-project/pull/120
-[135]: https://github.com/taiki-e/pin-project/pull/135
-
 ## [0.4.2] - 2019-09-29
 
-**Note: This release has been yanked.** See [#148] for details.
+**Note: This release has been yanked.** See [#148](https://github.com/taiki-e/pin-project/pull/148) for details.
 
-- [Fixed support for DSTs(Dynamically Sized Types).][113]
-
-[113]: https://github.com/taiki-e/pin-project/pull/113
+- [Fixed 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] for details.
+**Note: This release has been yanked.** See [#148](https://github.com/taiki-e/pin-project/pull/148) for details.
 
-- [Fixed an issue that caused an error when using `#[pin_project]` on a type that has `#[pin]` + `!Unpin` field with no generics or lifetime.][111]
-
-[111]: https://github.com/taiki-e/pin-project/pull/111
+- [Fixed 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] for details.
+**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.**][18] In the absence of other unsafe code that you write, it is impossible to cause undefined behavior.
+- [**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][18], [#33][33])
+- `#[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.][18]
+- [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][18], [#33][33], [#86][86])
+- 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.][18]
+- [`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.][96]
+- [`#[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.][53]
+- [`#[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()]`.][77]
+- [`#[pin_project]` can now interoperate with `#[cfg()]`.](https://github.com/taiki-e/pin-project/pull/77)
 
-- [Added `project_ref` method to `#[pin_project]` types.][93]
+- [Added `project_ref` method to `#[pin_project]` types.](https://github.com/taiki-e/pin-project/pull/93)
 
-- [Added `#[project_ref]` attribute.][93]
+- [Added `#[project_ref]` attribute.](https://github.com/taiki-e/pin-project/pull/93)
 
-- [Removed "project_attr" feature and always enable `#[project]` attribute.][94]
+- [Removed "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.][46]
+- [`#[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.][85]
+- [`#[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.][51]
+- [`#[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:
 
-- [Fixed 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.][107]
-
-[18]: https://github.com/taiki-e/pin-project/pull/18
-[33]: https://github.com/taiki-e/pin-project/pull/107
-[107]: https://github.com/taiki-e/pin-project/pull/107
+- [Fixed 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
 
-- [Changed the argument type of project method back to `self: Pin<&mut Self>`.][90]
+- [Changed the argument type of project method back to `self: Pin<&mut Self>`.](https://github.com/taiki-e/pin-project/pull/90)
 
-- [Removed "project_attr" feature and always enable `#[project]` attribute.][94]
+- [Removed "project_attr" feature and always enable `#[project]` attribute.](https://github.com/taiki-e/pin-project/pull/94)
 
-- [Removed "renamed" feature.][100]
+- [Removed "renamed" feature.](https://github.com/taiki-e/pin-project/pull/100)
 
-- [`#[project]` attribute can now be used for `use` statements.][85]
+- [`#[project]` attribute can now be used for `use` statements.](https://github.com/taiki-e/pin-project/pull/85)
 
-- [Added `project_ref` method and `#[project_ref]` attribute.][93]
+- [Added `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.][96]
-
-[85]: https://github.com/taiki-e/pin-project/pull/85
-[90]: https://github.com/taiki-e/pin-project/pull/90
-[93]: https://github.com/taiki-e/pin-project/pull/93
-[94]: https://github.com/taiki-e/pin-project/pull/94
-[96]: https://github.com/taiki-e/pin-project/pull/96
-[100]: https://github.com/taiki-e/pin-project/pull/100
+- [`#[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
 
-- [Changed #[pinned_drop] to trait implementation.][86]
+- [Changed #[pinned_drop] to trait implementation.](https://github.com/taiki-e/pin-project/pull/86)
 
   ```rust
   #[pinned_drop]
@@ -491,19 +428,15 @@
 
 - Diagnostic improvements.
 
-[86]: https://github.com/taiki-e/pin-project/pull/86
-
 ## [0.4.0-alpha.10] - 2019-09-07
 
-- [`#[pin_project]` can now interoperate with `#[cfg()]`.][77]
+- [`#[pin_project]` can now interoperate with `#[cfg()]`.](https://github.com/taiki-e/pin-project/pull/77)
 
 - Documentation improvements.
 
-[77]: https://github.com/taiki-e/pin-project/pull/77
-
 ## [0.4.0-alpha.9] - 2019-09-05
 
-- [Added 'project_into' method to `#[pin_project]` types][69]. This can be useful when returning a pin projection from a method.
+- [Added '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> {
@@ -511,37 +444,25 @@
   }
   ```
 
-- [Prevented UnpinStruct from appearing in the document by default.][71] See [#71][71] for more details.
-
-[69]: https://github.com/taiki-e/pin-project/pull/69
-[71]: https://github.com/taiki-e/pin-project/pull/69
+- [Prevented 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
 
-- [Improved document of generated code.][62]. Also added an option to control the document of generated code. See [#62][62] for more details.
+- [Improved 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.][61]
-
-[61]: https://github.com/taiki-e/pin-project/pull/61
-[62]: https://github.com/taiki-e/pin-project/pull/62
+- [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.][57]
-
-[57]: https://github.com/taiki-e/pin-project/pull/57
+- [Suppress `dead_code` lint in generated types.](https://github.com/taiki-e/pin-project/pull/57)
 
 ## [0.4.0-alpha.6] - 2019-09-01
 
-- [Allowed using `#[pin_project]` type with private field types][53]
-
-[53]: https://github.com/taiki-e/pin-project/pull/53
+- [Allowed 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.][51]
-
-[51]: https://github.com/taiki-e/pin-project/pull/51
+- [`#[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
 
@@ -549,15 +470,11 @@
 
 ## [0.4.0-alpha.3] - 2019-08-23
 
-- [Changed `project` method generated by `#[pin_project]` attribute to take an `&mut Pin<&mut Self>` argument.][47]
+- [Changed `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.][46]
+- [`#[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.][48] This removed some restrictions.
-
-[46]: https://github.com/taiki-e/pin-project/pull/46
-[47]: https://github.com/taiki-e/pin-project/pull/47
-[48]: https://github.com/taiki-e/pin-project/pull/48
+- [`#[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
 
@@ -577,9 +494,7 @@
 
 - Made `#[project]` attribute disabled by default.
 
-See also [tracking issue for 0.4 release][21].
-
-[21]: https://github.com/taiki-e/pin-project/issues/21
+See also [tracking issue for 0.4 release](https://github.com/taiki-e/pin-project/issues/21).
 
 ## [0.3.5] - 2019-08-14
 
@@ -591,12 +506,10 @@
 
 ## [0.3.3] - 2019-07-15
 
-**Note: This release has been yanked.** See [#16] for details.
+**Note: This release has been yanked.** See [#16](https://github.com/taiki-e/pin-project/issues/16) for details.
 
 - Diagnostic improvements.
 
-[#16]: https://github.com/taiki-e/pin-project/issues/16
-
 ## [0.3.2] - 2019-03-30
 
 - Avoided suffixes on tuple index.
@@ -671,7 +584,9 @@
 
 Initial release
 
-[Unreleased]: https://github.com/taiki-e/pin-project/compare/v1.0.3...HEAD
+[Unreleased]: https://github.com/taiki-e/pin-project/compare/v1.0.5...HEAD
+[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
diff --git a/Cargo.toml b/Cargo.toml
index 79ba823..f77b1cb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,12 +13,11 @@
 [package]
 edition = "2018"
 name = "pin-project"
-version = "1.0.3"
+version = "1.0.5"
 authors = ["Taiki Endo <te316e89@gmail.com>"]
-exclude = ["/.github", "/ci", "/scripts"]
+exclude = ["/.*", "/ci", "/scripts"]
 description = "A crate for safe and ergonomic pin-projection.\n"
 documentation = "https://docs.rs/pin-project"
-readme = "README.md"
 keywords = ["pin", "macros", "attribute"]
 categories = ["no-std", "rust-patterns"]
 license = "Apache-2.0 OR MIT"
@@ -26,16 +25,16 @@
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
 [dependencies.pin-project-internal]
-version = "=1.0.3"
+version = "=1.0.5"
 default-features = false
+[dev-dependencies.macrotest]
+version = "1.0.8"
+
 [dev-dependencies.rustversion]
 version = "1"
 
 [dev-dependencies.static_assertions]
 version = "1"
 
-[dev-dependencies.tempfile]
-version = "3"
-
 [dev-dependencies.trybuild]
 version = "1"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 401635c..454fee7 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "pin-project"
-version = "1.0.3"
+version = "1.0.5"
 authors = ["Taiki Endo <te316e89@gmail.com>"]
 edition = "2018"
 license = "Apache-2.0 OR MIT"
@@ -8,8 +8,7 @@
 documentation = "https://docs.rs/pin-project"
 keywords = ["pin", "macros", "attribute"]
 categories = ["no-std", "rust-patterns"]
-readme = "README.md"
-exclude = ["/.github", "/ci", "/scripts"]
+exclude = ["/.*", "/ci", "/scripts"]
 description = """
 A crate for safe and ergonomic pin-projection.
 """
@@ -22,18 +21,17 @@
     "pin-project-internal",
     "tests/auxiliary/macro",
     "tests/doc",
-    "tests/expand",
     "tests/no-core",
     "tests/no-std",
     "tests/rust-2015",
 ]
 
 [dependencies]
-pin-project-internal = { version = "=1.0.3", path = "pin-project-internal", default-features = false }
+pin-project-internal = { version = "=1.0.5", path = "pin-project-internal", default-features = false }
 
 [dev-dependencies]
 pin-project-auxiliary-macro = { path = "tests/auxiliary/macro" }
+macrotest = "1.0.8"
 rustversion = "1"
 static_assertions = "1"
-tempfile = "3"
 trybuild = "1"
diff --git a/METADATA b/METADATA
index b15e8a5..2bf8bbe 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/pin-project/pin-project-1.0.3.crate"
+    value: "https://static.crates.io/crates/pin-project/pin-project-1.0.5.crate"
   }
-  version: "1.0.3"
+  version: "1.0.5"
   license_type: NOTICE
   last_upgrade_date {
     year: 2021
-    month: 1
-    day: 5
+    month: 2
+    day: 9
   }
 }
diff --git a/README.md b/README.md
index e98bff2..95818e1 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,10 @@
 # pin-project
 
-[![crates.io](https://img.shields.io/crates/v/pin-project.svg?style=flat-square&logo=rust)](https://crates.io/crates/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)](https://docs.rs/pin-project)
-[![license](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue.svg?style=flat-square)](#license)
-[![rustc](https://img.shields.io/badge/rustc-1.37+-blue.svg?style=flat-square)](https://www.rust-lang.org)
-[![build status](https://img.shields.io/github/workflow/status/taiki-e/pin-project/CI/master?style=flat-square)](https://github.com/taiki-e/pin-project/actions?query=workflow%3ACI+branch%3Amaster)
+[![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/master?style=flat-square&logo=github)](https://github.com/taiki-e/pin-project/actions)
 
 A crate for safe and ergonomic [pin-projection].
 
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 7d1919a..7e10dd0 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,11 +1,7 @@
-// Generated by cargo2android.py for tests in Android.bp
+// Generated by update_crate_tests.py for tests that depend on this crate.
 {
   "presubmit": [
     {
-      "host": true,
-      "name": "futures-util_host_test_src_lib"
-    },
-    {
       "name": "futures-util_device_test_src_lib"
     }
   ]
diff --git a/examples/pinned_drop-expanded.rs b/examples/pinned_drop-expanded.rs
index ad22c0b..48eb7fc 100644
--- a/examples/pinned_drop-expanded.rs
+++ b/examples/pinned_drop-expanded.rs
@@ -3,9 +3,10 @@
 // ```rust
 // #![allow(dead_code)]
 //
-// use pin_project::{pin_project, pinned_drop};
 // use std::pin::Pin;
 //
+// use pin_project::{pin_project, pinned_drop};
+//
 // #[pin_project(PinnedDrop)]
 // pub struct Struct<'a, T> {
 //     was_dropped: &'a mut bool,
@@ -24,9 +25,10 @@
 #![allow(dead_code, unused_imports, unused_parens, unknown_lints, renamed_and_removed_lints)]
 #![allow(clippy::needless_lifetimes)]
 
-use pin_project::{pin_project, pinned_drop};
 use std::pin::Pin;
 
+use pin_project::{pin_project, pinned_drop};
+
 // #[pin_project(PinnedDrop)]
 pub struct Struct<'a, T> {
     was_dropped: &'a mut bool,
diff --git a/examples/pinned_drop.rs b/examples/pinned_drop.rs
index 4dfd228..6fb8719 100644
--- a/examples/pinned_drop.rs
+++ b/examples/pinned_drop.rs
@@ -2,9 +2,10 @@
 
 #![allow(dead_code)]
 
-use pin_project::{pin_project, pinned_drop};
 use std::pin::Pin;
 
+use pin_project::{pin_project, pinned_drop};
+
 #[pin_project(PinnedDrop)]
 pub struct Struct<'a, T> {
     was_dropped: &'a mut bool,
diff --git a/examples/project_replace-expanded.rs b/examples/project_replace-expanded.rs
index ec00d41..4f43bda 100644
--- a/examples/project_replace-expanded.rs
+++ b/examples/project_replace-expanded.rs
@@ -76,13 +76,6 @@
         ) -> __StructProjectionOwned<T, U> {
             unsafe {
                 let __self_ptr: *mut Self = self.get_unchecked_mut();
-                let Self { pinned, unpinned } = &mut *__self_ptr;
-
-                // First, extract all the unpinned fields
-                let __result = __StructProjectionOwned {
-                    pinned: ::pin_project::__private::PhantomData,
-                    unpinned: ::pin_project::__private::ptr::read(unpinned),
-                };
 
                 // Destructors will run in reverse order, so next create a guard to overwrite
                 // `self` with the replacement value without calling destructors.
@@ -91,6 +84,14 @@
                     value: ::pin_project::__private::ManuallyDrop::new(__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)
diff --git a/src/lib.rs b/src/lib.rs
index 37e33e6..12cef30 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,9 +6,10 @@
 //! covering all the fields of struct or enum.
 //!
 //! ```rust
-//! use pin_project::pin_project;
 //! use std::pin::Pin;
 //!
+//! use pin_project::pin_project;
+//!
 //! #[pin_project]
 //! struct Struct<T, U> {
 //!     #[pin]
@@ -31,9 +32,10 @@
 //! returned from the method.
 //!
 //! ```rust
-//! use pin_project::pin_project;
 //! use std::pin::Pin;
 //!
+//! use pin_project::pin_project;
+//!
 //! #[pin_project(project = EnumProj)]
 //! enum Enum<T, U> {
 //!     Pinned(#[pin] T),
@@ -82,7 +84,6 @@
 
 #[doc(inline)]
 pub use pin_project_internal::pin_project;
-
 #[doc(inline)]
 pub use pin_project_internal::pinned_drop;
 
@@ -158,11 +159,11 @@
         ptr,
     };
 
-    use super::UnsafeUnpin;
-
     #[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.**
diff --git a/src/lib.rs.orig b/src/lib.rs.orig
index b7a20ed..2aacb81 100644
--- a/src/lib.rs.orig
+++ b/src/lib.rs.orig
@@ -6,9 +6,10 @@
 //! covering all the fields of struct or enum.
 //!
 //! ```rust
-//! use pin_project::pin_project;
 //! use std::pin::Pin;
 //!
+//! use pin_project::pin_project;
+//!
 //! #[pin_project]
 //! struct Struct<T, U> {
 //!     #[pin]
@@ -31,9 +32,10 @@
 //! returned from the method.
 //!
 //! ```rust
-//! use pin_project::pin_project;
 //! use std::pin::Pin;
 //!
+//! use pin_project::pin_project;
+//!
 //! #[pin_project(project = EnumProj)]
 //! enum Enum<T, U> {
 //!     Pinned(#[pin] T),
@@ -79,7 +81,6 @@
 
 #[doc(inline)]
 pub use pin_project_internal::pin_project;
-
 #[doc(inline)]
 pub use pin_project_internal::pinned_drop;
 
@@ -155,11 +156,11 @@
         ptr,
     };
 
-    use super::UnsafeUnpin;
-
     #[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.**
diff --git a/tests/auxiliary/mod.rs b/tests/auxiliary/mod.rs
index a0eb7c2..1457099 100644
--- a/tests/auxiliary/mod.rs
+++ b/tests/auxiliary/mod.rs
@@ -1,9 +1,4 @@
 #![allow(dead_code, unused_macros)]
-#![allow(box_pointers, unreachable_pub)]
-#![allow(clippy::restriction)]
-
-use std::{env, fs, path::Path, process::Command};
-use tempfile::Builder;
 
 macro_rules! assert_unpin {
     ($ty:ty) => {
@@ -15,30 +10,3 @@
         static_assertions::assert_not_impl_all!($ty: Unpin);
     };
 }
-
-#[rustversion::attr(since(1.46), track_caller)]
-pub fn assert_diff(expected_path: impl AsRef<Path>, actual: impl AsRef<str>) {
-    let actual = actual.as_ref();
-    let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
-    let expected_path = &manifest_dir.join(expected_path);
-    (|| -> Result<(), Box<dyn std::error::Error>> {
-        let expected = fs::read_to_string(expected_path)?;
-        if expected != actual {
-            if env::var_os("CI").is_some() {
-                let outdir = Builder::new().prefix("assert_diff").tempdir()?;
-                let actual_path = &outdir.path().join(expected_path.file_name().unwrap());
-                fs::write(actual_path, actual)?;
-                let status = Command::new("git")
-                    .args(&["--no-pager", "diff", "--no-index", "--"])
-                    .args(&[expected_path, actual_path])
-                    .status()?;
-                assert!(!status.success());
-                panic!("assertion failed");
-            } else {
-                fs::write(expected_path, actual)?;
-            }
-        }
-        Ok(())
-    })()
-    .unwrap_or_else(|e| panic!("{}", e))
-}
diff --git a/tests/cfg.rs b/tests/cfg.rs
index 2fdcfbb..2f5387b 100644
--- a/tests/cfg.rs
+++ b/tests/cfg.rs
@@ -6,16 +6,14 @@
 #[macro_use]
 mod auxiliary;
 
-use pin_project::pin_project;
 use std::{marker::PhantomPinned, pin::Pin};
 
-#[cfg(target_os = "linux")]
-struct Linux;
-#[cfg(not(target_os = "linux"))]
-struct Other;
+use pin_project::pin_project;
+
+struct Always;
 
 // Use this type to check that `cfg(any())` is working properly.
-struct Any(PhantomPinned);
+struct Never(PhantomPinned);
 
 #[test]
 fn cfg() {
@@ -23,63 +21,45 @@
 
     #[pin_project(project_replace)]
     struct SameName {
-        #[cfg(target_os = "linux")]
+        #[cfg(not(any()))]
         #[pin]
-        inner: Linux,
-        #[cfg(not(target_os = "linux"))]
-        #[pin]
-        inner: Other,
+        inner: Always,
         #[cfg(any())]
         #[pin]
-        any: Any,
+        inner: Never,
     }
 
     assert_unpin!(SameName);
 
-    #[cfg(target_os = "linux")]
-    let _ = SameName { inner: Linux };
-    #[cfg(not(target_os = "linux"))]
-    let _ = SameName { inner: Other };
+    let _ = SameName { inner: Always };
 
     #[pin_project(project_replace)]
     struct DifferentName {
-        #[cfg(target_os = "linux")]
+        #[cfg(not(any()))]
         #[pin]
-        l: Linux,
-        #[cfg(not(target_os = "linux"))]
-        #[pin]
-        o: Other,
+        a: Always,
         #[cfg(any())]
         #[pin]
-        a: Any,
+        n: Never,
     }
 
     assert_unpin!(DifferentName);
 
-    #[cfg(target_os = "linux")]
-    let _ = DifferentName { l: Linux };
-    #[cfg(not(target_os = "linux"))]
-    let _ = DifferentName { o: Other };
+    let _ = DifferentName { a: Always };
 
     #[pin_project(project_replace)]
     struct TupleStruct(
-        #[cfg(target_os = "linux")]
+        #[cfg(not(any()))]
         #[pin]
-        Linux,
-        #[cfg(not(target_os = "linux"))]
-        #[pin]
-        Other,
+        Always,
         #[cfg(any())]
         #[pin]
-        Any,
+        Never,
     );
 
     assert_unpin!(TupleStruct);
 
-    #[cfg(target_os = "linux")]
-    let _ = TupleStruct(Linux);
-    #[cfg(not(target_os = "linux"))]
-    let _ = TupleStruct(Other);
+    let _ = TupleStruct(Always);
 
     // enums
 
@@ -89,30 +69,21 @@
         project_replace = VariantProjOwn,
     )]
     enum Variant {
-        #[cfg(target_os = "linux")]
-        Inner(#[pin] Linux),
-        #[cfg(not(target_os = "linux"))]
-        Inner(#[pin] Other),
-
-        #[cfg(target_os = "linux")]
-        Linux(#[pin] Linux),
-        #[cfg(not(target_os = "linux"))]
-        Other(#[pin] Other),
+        #[cfg(not(any()))]
+        Inner(#[pin] Always),
         #[cfg(any())]
-        Any(#[pin] Any),
+        Inner(#[pin] Never),
+
+        #[cfg(not(any()))]
+        A(#[pin] Always),
+        #[cfg(any())]
+        N(#[pin] Never),
     }
 
     assert_unpin!(Variant);
 
-    #[cfg(target_os = "linux")]
-    let _ = Variant::Inner(Linux);
-    #[cfg(not(target_os = "linux"))]
-    let _ = Variant::Inner(Other);
-
-    #[cfg(target_os = "linux")]
-    let _ = Variant::Linux(Linux);
-    #[cfg(not(target_os = "linux"))]
-    let _ = Variant::Other(Other);
+    let _ = Variant::Inner(Always);
+    let _ = Variant::A(Always);
 
     #[pin_project(
         project = FieldProj,
@@ -121,111 +92,71 @@
     )]
     enum Field {
         SameName {
-            #[cfg(target_os = "linux")]
+            #[cfg(not(any()))]
             #[pin]
-            inner: Linux,
-            #[cfg(not(target_os = "linux"))]
-            #[pin]
-            inner: Other,
+            inner: Always,
             #[cfg(any())]
             #[pin]
-            any: Any,
+            inner: Never,
         },
         DifferentName {
-            #[cfg(target_os = "linux")]
+            #[cfg(not(any()))]
             #[pin]
-            l: Linux,
-            #[cfg(not(target_os = "linux"))]
-            #[pin]
-            w: Other,
+            a: Always,
             #[cfg(any())]
             #[pin]
-            any: Any,
+            n: Never,
         },
         TupleVariant(
-            #[cfg(target_os = "linux")]
+            #[cfg(not(any()))]
             #[pin]
-            Linux,
-            #[cfg(not(target_os = "linux"))]
-            #[pin]
-            Other,
+            Always,
             #[cfg(any())]
             #[pin]
-            Any,
+            Never,
         ),
     }
 
     assert_unpin!(Field);
 
-    #[cfg(target_os = "linux")]
-    let _ = Field::SameName { inner: Linux };
-    #[cfg(not(target_os = "linux"))]
-    let _ = Field::SameName { inner: Other };
-
-    #[cfg(target_os = "linux")]
-    let _ = Field::DifferentName { l: Linux };
-    #[cfg(not(target_os = "linux"))]
-    let _ = Field::DifferentName { w: Other };
-
-    #[cfg(target_os = "linux")]
-    let _ = Field::TupleVariant(Linux);
-    #[cfg(not(target_os = "linux"))]
-    let _ = Field::TupleVariant(Other);
+    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(target_os = "linux")]
-        #[cfg_attr(target_os = "linux", pin)]
-        inner: Linux,
-        #[cfg(not(target_os = "linux"))]
-        #[cfg_attr(not(target_os = "linux"), pin)]
-        inner: Other,
+        #[cfg(not(any()))]
+        #[cfg_attr(not(any()), pin)]
+        inner: Always,
         #[cfg(any())]
         #[cfg_attr(any(), pin)]
-        any: Any,
+        inner: Never,
     }
 
     assert_unpin!(SameCfg);
 
-    #[cfg(target_os = "linux")]
-    let mut x = SameCfg { inner: Linux };
-    #[cfg(not(target_os = "linux"))]
-    let mut x = SameCfg { inner: Other };
-
+    let mut x = SameCfg { inner: Always };
     let x = Pin::new(&mut x).project();
-    #[cfg(target_os = "linux")]
-    let _: Pin<&mut Linux> = x.inner;
-    #[cfg(not(target_os = "linux"))]
-    let _: Pin<&mut Other> = x.inner;
+    let _: Pin<&mut Always> = x.inner;
 
     #[pin_project(project_replace)]
     struct DifferentCfg {
-        #[cfg(target_os = "linux")]
-        #[cfg_attr(target_os = "linux", pin)]
-        inner: Linux,
-        #[cfg(not(target_os = "linux"))]
-        #[cfg_attr(target_os = "linux", pin)]
-        inner: Other,
-        #[cfg(any())]
+        #[cfg(not(any()))]
         #[cfg_attr(any(), pin)]
-        any: Any,
+        inner: Always,
+        #[cfg(any())]
+        #[cfg_attr(not(any()), pin)]
+        inner: Never,
     }
 
     assert_unpin!(DifferentCfg);
 
-    #[cfg(target_os = "linux")]
-    let mut x = DifferentCfg { inner: Linux };
-    #[cfg(not(target_os = "linux"))]
-    let mut x = DifferentCfg { inner: Other };
-
+    let mut x = DifferentCfg { inner: Always };
     let x = Pin::new(&mut x).project();
-    #[cfg(target_os = "linux")]
-    let _: Pin<&mut Linux> = x.inner;
-    #[cfg(not(target_os = "linux"))]
-    let _: &mut Other = x.inner;
+    let _: &mut Always = x.inner;
 
     #[cfg_attr(not(any()), pin_project)]
     struct Foo<T> {
diff --git a/tests/compiletest.rs b/tests/compiletest.rs
index 85b1db8..e3d713a 100644
--- a/tests/compiletest.rs
+++ b/tests/compiletest.rs
@@ -3,8 +3,7 @@
 
 use std::env;
 
-// Run `./dev.sh +$toolchain test --test compiletest` to update this.
-#[rustversion::attr(before(2020-11-25), ignore)] // Note: This date is commit-date and the day before the toolchain date.
+#[rustversion::attr(before(2021-01-08), ignore)] // Note: This date is commit-date and the day before the toolchain date.
 #[test]
 fn ui() {
     if env::var_os("CI").is_none() {
@@ -12,10 +11,5 @@
     }
 
     let t = trybuild::TestCases::new();
-    t.compile_fail("tests/ui/cfg/*.rs");
-    t.compile_fail("tests/ui/not_unpin/*.rs");
-    t.compile_fail("tests/ui/pin_project/*.rs");
-    t.compile_fail("tests/ui/pinned_drop/*.rs");
-    t.compile_fail("tests/ui/unsafe_unpin/*.rs");
-    t.compile_fail("tests/ui/unstable-features/*.rs");
+    t.compile_fail("tests/ui/*/*.rs");
 }
diff --git a/tests/drop_order.rs b/tests/drop_order.rs
index 1557188..8ced56e 100644
--- a/tests/drop_order.rs
+++ b/tests/drop_order.rs
@@ -2,9 +2,10 @@
 
 // Refs: https://doc.rust-lang.org/reference/destructors.html
 
-use pin_project::pin_project;
 use std::{cell::Cell, pin::Pin, thread};
 
+use pin_project::pin_project;
+
 struct D<'a>(&'a Cell<usize>, usize);
 
 impl Drop for D<'_> {
diff --git a/tests/expand/README.md b/tests/expand/README.md
new file mode 100644
index 0000000..e3e708d
--- /dev/null
+++ b/tests/expand/README.md
@@ -0,0 +1,17 @@
+# Expansion tests
+
+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.
diff --git a/tests/expand/default/enum.expanded.rs b/tests/expand/default/enum.expanded.rs
new file mode 100644
index 0000000..490c6b0
--- /dev/null
+++ b/tests/expand/default/enum.expanded.rs
@@ -0,0 +1,131 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    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::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(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
index 0000000..ff05615
--- /dev/null
+++ b/tests/expand/default/enum.rs
@@ -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
index 0000000..ac878b8
--- /dev/null
+++ b/tests/expand/default/struct.expanded.rs
@@ -0,0 +1,113 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __StructProjection<'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(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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,
+                }
+            }
+        }
+        #[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(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
index 0000000..474f0a1
--- /dev/null
+++ b/tests/expand/default/struct.rs
@@ -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
index 0000000..0c5cc1d
--- /dev/null
+++ b/tests/expand/default/tuple_struct.expanded.rs
@@ -0,0 +1,101 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __TupleStructProjection<'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(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __TupleStructProjectionRef<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    impl<T, U> TupleStruct<T, U> {
+        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(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(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
index 0000000..398b14f
--- /dev/null
+++ b/tests/expand/default/tuple_struct.rs
@@ -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
index 0000000..75e1efe
--- /dev/null
+++ b/tests/expand/multifields/enum.expanded.rs
@@ -0,0 +1,246 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    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::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(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,
+                }
+            }
+        }
+        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 {
+                    target: __self_ptr,
+                    value: ::pin_project::__private::ManuallyDrop::new(__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(pinned2);
+                            let __guard = ::pin_project::__private::UnsafeDropInPlaceGuard(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(_1);
+                            let __guard = ::pin_project::__private::UnsafeDropInPlaceGuard(_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
index 0000000..754d48c
--- /dev/null
+++ b/tests/expand/multifields/enum.rs
@@ -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
index 0000000..bd4e6e3
--- /dev/null
+++ b/tests/expand/multifields/struct.expanded.rs
@@ -0,0 +1,181 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[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> {
+        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(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,
+                }
+            }
+        }
+        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 {
+                    target: __self_ptr,
+                    value: ::pin_project::__private::ManuallyDrop::new(__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(pinned2);
+                    let __guard = ::pin_project::__private::UnsafeDropInPlaceGuard(pinned1);
+                }
+                __result
+            }
+        }
+    }
+    #[forbid(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
index 0000000..3b319bf
--- /dev/null
+++ b/tests/expand/multifields/struct.rs
@@ -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
index 0000000..1ec045c
--- /dev/null
+++ b/tests/expand/multifields/tuple_struct.expanded.rs
@@ -0,0 +1,157 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[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> {
+        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(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,
+                )
+            }
+        }
+        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 {
+                    target: __self_ptr,
+                    value: ::pin_project::__private::ManuallyDrop::new(__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(_1);
+                    let __guard = ::pin_project::__private::UnsafeDropInPlaceGuard(_0);
+                }
+                __result
+            }
+        }
+    }
+    #[forbid(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
index 0000000..bc92eee
--- /dev/null
+++ b/tests/expand/multifields/tuple_struct.rs
@@ -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
index 0000000..22d1b8f
--- /dev/null
+++ b/tests/expand/naming/enum-all.expanded.rs
@@ -0,0 +1,187 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    impl<T, U> Enum<T, U> {
+        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(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,
+                }
+            }
+        }
+        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 {
+                    target: __self_ptr,
+                    value: ::pin_project::__private::ManuallyDrop::new(__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(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(_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
index 0000000..dd513e6
--- /dev/null
+++ b/tests/expand/naming/enum-all.rs
@@ -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
index 0000000..fec425c
--- /dev/null
+++ b/tests/expand/naming/enum-mut.expanded.rs
@@ -0,0 +1,90 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    impl<T, U> Enum<T, U> {
+        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
index 0000000..818276f
--- /dev/null
+++ b/tests/expand/naming/enum-mut.rs
@@ -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
index 0000000..a44ee5f
--- /dev/null
+++ b/tests/expand/naming/enum-none.expanded.rs
@@ -0,0 +1,53 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    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
index 0000000..a87438d
--- /dev/null
+++ b/tests/expand/naming/enum-none.rs
@@ -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
index 0000000..091ad37
--- /dev/null
+++ b/tests/expand/naming/enum-own.expanded.rs
@@ -0,0 +1,112 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    impl<T, U> Enum<T, U> {
+        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 {
+                    target: __self_ptr,
+                    value: ::pin_project::__private::ManuallyDrop::new(__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(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(_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
index 0000000..cf88697
--- /dev/null
+++ b/tests/expand/naming/enum-own.rs
@@ -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
index 0000000..5d3c4c9
--- /dev/null
+++ b/tests/expand/naming/enum-ref.expanded.rs
@@ -0,0 +1,93 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    impl<T, U> Enum<T, U> {
+        #[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
index 0000000..b1ff805
--- /dev/null
+++ b/tests/expand/naming/enum-ref.rs
@@ -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
index 0000000..660a05a
--- /dev/null
+++ b/tests/expand/naming/struct-all.expanded.rs
@@ -0,0 +1,145 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    impl<T, U> Struct<T, U> {
+        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(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,
+                }
+            }
+        }
+        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 {
+                    target: __self_ptr,
+                    value: ::pin_project::__private::ManuallyDrop::new(__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(pinned);
+                }
+                __result
+            }
+        }
+    }
+    #[forbid(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
index 0000000..c229ba4
--- /dev/null
+++ b/tests/expand/naming/struct-all.rs
@@ -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
index 0000000..91552e7
--- /dev/null
+++ b/tests/expand/naming/struct-mut.expanded.rs
@@ -0,0 +1,111 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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>) -> Proj<'pin, T, U> {
+            unsafe {
+                let Self { pinned, unpinned } = self.get_unchecked_mut();
+                Proj {
+                    pinned: ::pin_project::__private::Pin::new_unchecked(pinned),
+                    unpinned,
+                }
+            }
+        }
+        #[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(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
index 0000000..2f554d3
--- /dev/null
+++ b/tests/expand/naming/struct-mut.rs
@@ -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
index 0000000..ac878b8
--- /dev/null
+++ b/tests/expand/naming/struct-none.expanded.rs
@@ -0,0 +1,113 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __StructProjection<'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(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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,
+                }
+            }
+        }
+        #[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(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
index 0000000..474f0a1
--- /dev/null
+++ b/tests/expand/naming/struct-none.rs
@@ -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
index 0000000..6f4de78
--- /dev/null
+++ b/tests/expand/naming/struct-own.expanded.rs
@@ -0,0 +1,147 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __StructProjection<'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(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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,
+                }
+            }
+        }
+        #[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,
+                }
+            }
+        }
+        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 {
+                    target: __self_ptr,
+                    value: ::pin_project::__private::ManuallyDrop::new(__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(pinned);
+                }
+                __result
+            }
+        }
+    }
+    #[forbid(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
index 0000000..4924362
--- /dev/null
+++ b/tests/expand/naming/struct-own.rs
@@ -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
index 0000000..3296c02
--- /dev/null
+++ b/tests/expand/naming/struct-ref.expanded.rs
@@ -0,0 +1,113 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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> {
+        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(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(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
index 0000000..4e29a16
--- /dev/null
+++ b/tests/expand/naming/struct-ref.rs
@@ -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
index 0000000..b78ebf8
--- /dev/null
+++ b/tests/expand/naming/tuple_struct-all.expanded.rs
@@ -0,0 +1,124 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    impl<T, U> TupleStruct<T, U> {
+        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(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)
+            }
+        }
+        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 {
+                    target: __self_ptr,
+                    value: ::pin_project::__private::ManuallyDrop::new(__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(_0);
+                }
+                __result
+            }
+        }
+    }
+    #[forbid(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
index 0000000..0d95cb0
--- /dev/null
+++ b/tests/expand/naming/tuple_struct-all.rs
@@ -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
index 0000000..96aa951
--- /dev/null
+++ b/tests/expand/naming/tuple_struct-mut.expanded.rs
@@ -0,0 +1,96 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __TupleStructProjectionRef<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    impl<T, U> TupleStruct<T, U> {
+        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(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(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
index 0000000..e9779a6
--- /dev/null
+++ b/tests/expand/naming/tuple_struct-mut.rs
@@ -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
index 0000000..0c5cc1d
--- /dev/null
+++ b/tests/expand/naming/tuple_struct-none.expanded.rs
@@ -0,0 +1,101 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __TupleStructProjection<'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(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __TupleStructProjectionRef<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    impl<T, U> TupleStruct<T, U> {
+        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(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(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
index 0000000..398b14f
--- /dev/null
+++ b/tests/expand/naming/tuple_struct-none.rs
@@ -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
index 0000000..08d9ae3
--- /dev/null
+++ b/tests/expand/naming/tuple_struct-own.expanded.rs
@@ -0,0 +1,132 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __TupleStructProjection<'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(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __TupleStructProjectionRef<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    impl<T, U> TupleStruct<T, U> {
+        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(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)
+            }
+        }
+        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 {
+                    target: __self_ptr,
+                    value: ::pin_project::__private::ManuallyDrop::new(__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(_0);
+                }
+                __result
+            }
+        }
+    }
+    #[forbid(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
index 0000000..a15ad40
--- /dev/null
+++ b/tests/expand/naming/tuple_struct-own.rs
@@ -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
index 0000000..e06bf0c
--- /dev/null
+++ b/tests/expand/naming/tuple_struct-ref.expanded.rs
@@ -0,0 +1,98 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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> {
+        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(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(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
index 0000000..cc61edf
--- /dev/null
+++ b/tests/expand/naming/tuple_struct-ref.rs
@@ -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
index 0000000..8d25786
--- /dev/null
+++ b/tests/expand/not_unpin/enum.expanded.rs
@@ -0,0 +1,121 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    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::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(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
index 0000000..ac0b3b8
--- /dev/null
+++ b/tests/expand/not_unpin/enum.rs
@@ -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
index 0000000..9d58022
--- /dev/null
+++ b/tests/expand/not_unpin/struct.expanded.rs
@@ -0,0 +1,104 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __StructProjection<'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(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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,
+                }
+            }
+        }
+        #[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(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
index 0000000..233e6d4
--- /dev/null
+++ b/tests/expand/not_unpin/struct.rs
@@ -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
index 0000000..525513e
--- /dev/null
+++ b/tests/expand/not_unpin/tuple_struct.expanded.rs
@@ -0,0 +1,92 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __TupleStructProjection<'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(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __TupleStructProjectionRef<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    impl<T, U> TupleStruct<T, U> {
+        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(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(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
index 0000000..c8065db
--- /dev/null
+++ b/tests/expand/not_unpin/tuple_struct.rs
@@ -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
index 0000000..7978ba3
--- /dev/null
+++ b/tests/expand/pinned_drop/enum.expanded.rs
@@ -0,0 +1,142 @@
+use pin_project::{pin_project, pinned_drop};
+use std::pin::Pin;
+# [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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    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::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(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);
+            }
+        }
+    }
+};
+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
index 0000000..f5b8aa4
--- /dev/null
+++ b/tests/expand/pinned_drop/enum.rs
@@ -0,0 +1,22 @@
+use pin_project::{pin_project, pinned_drop};
+use std::pin::Pin;
+
+#[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
index 0000000..1bdeda4
--- /dev/null
+++ b/tests/expand/pinned_drop/struct.expanded.rs
@@ -0,0 +1,124 @@
+use pin_project::{pin_project, pinned_drop};
+use std::pin::Pin;
+#[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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __StructProjection<'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(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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,
+                }
+            }
+        }
+        #[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(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);
+            }
+        }
+    }
+};
+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
index 0000000..948e6cc
--- /dev/null
+++ b/tests/expand/pinned_drop/struct.rs
@@ -0,0 +1,18 @@
+use pin_project::{pin_project, pinned_drop};
+use std::pin::Pin;
+
+#[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
index 0000000..f6cf250
--- /dev/null
+++ b/tests/expand/pinned_drop/tuple_struct.expanded.rs
@@ -0,0 +1,112 @@
+use pin_project::{pin_project, pinned_drop};
+use std::pin::Pin;
+#[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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __TupleStructProjection<'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(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __TupleStructProjectionRef<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    impl<T, U> TupleStruct<T, U> {
+        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(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(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);
+            }
+        }
+    }
+};
+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
index 0000000..a536039
--- /dev/null
+++ b/tests/expand/pinned_drop/tuple_struct.rs
@@ -0,0 +1,14 @@
+use pin_project::{pin_project, pinned_drop};
+use std::pin::Pin;
+
+#[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
index 0000000..6af358b
--- /dev/null
+++ b/tests/expand/project_replace/enum.expanded.rs
@@ -0,0 +1,112 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    impl<T, U> Enum<T, U> {
+        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 {
+                    target: __self_ptr,
+                    value: ::pin_project::__private::ManuallyDrop::new(__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(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(_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
index 0000000..d737f64
--- /dev/null
+++ b/tests/expand/project_replace/enum.rs
@@ -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
index 0000000..d210810
--- /dev/null
+++ b/tests/expand/project_replace/struct.expanded.rs
@@ -0,0 +1,147 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __StructProjection<'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(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __StructProjectionRef<'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(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    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,
+                }
+            }
+        }
+        #[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,
+                }
+            }
+        }
+        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 {
+                    target: __self_ptr,
+                    value: ::pin_project::__private::ManuallyDrop::new(__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(pinned);
+                }
+                __result
+            }
+        }
+    }
+    #[forbid(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
index 0000000..5865526
--- /dev/null
+++ b/tests/expand/project_replace/struct.rs
@@ -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
index 0000000..a48d502
--- /dev/null
+++ b/tests/expand/project_replace/tuple_struct.expanded.rs
@@ -0,0 +1,132 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __TupleStructProjection<'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(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __TupleStructProjectionRef<'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(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    struct __TupleStructProjectionOwned<T, U>(::pin_project::__private::PhantomData<T>, U);
+    impl<T, U> TupleStruct<T, U> {
+        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(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)
+            }
+        }
+        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 {
+                    target: __self_ptr,
+                    value: ::pin_project::__private::ManuallyDrop::new(__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(_0);
+                }
+                __result
+            }
+        }
+    }
+    #[forbid(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
index 0000000..c4d05f5
--- /dev/null
+++ b/tests/expand/project_replace/tuple_struct.rs
@@ -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
index 0000000..42396ac
--- /dev/null
+++ b/tests/expand/pub/enum.expanded.rs
@@ -0,0 +1,131 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    impl<T, U> Enum<T, U> {
+        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(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
index 0000000..7c8577f
--- /dev/null
+++ b/tests/expand/pub/enum.rs
@@ -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
index 0000000..34b1c79
--- /dev/null
+++ b/tests/expand/pub/struct.expanded.rs
@@ -0,0 +1,113 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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> {
+        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(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(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
index 0000000..f50d1e9
--- /dev/null
+++ b/tests/expand/pub/struct.rs
@@ -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
index 0000000..8dbcf91
--- /dev/null
+++ b/tests/expand/pub/tuple_struct.expanded.rs
@@ -0,0 +1,101 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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> {
+        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(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(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
index 0000000..5756aaf
--- /dev/null
+++ b/tests/expand/pub/tuple_struct.rs
@@ -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
index 0000000..faf87fc
--- /dev/null
+++ b/tests/expand/unsafe_unpin/enum.expanded.rs
@@ -0,0 +1,115 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::mut_mut)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(dead_code)]
+#[allow(clippy::ref_option_ref)]
+#[allow(clippy::type_repetition_in_bounds)]
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    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::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(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
index 0000000..d368d71
--- /dev/null
+++ b/tests/expand/unsafe_unpin/enum.rs
@@ -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
index 0000000..c01668e
--- /dev/null
+++ b/tests/expand/unsafe_unpin/struct.expanded.rs
@@ -0,0 +1,98 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __StructProjection<'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(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    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,
+                }
+            }
+        }
+        #[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(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
index 0000000..b0851b1
--- /dev/null
+++ b/tests/expand/unsafe_unpin/struct.rs
@@ -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
index 0000000..3c9afb8
--- /dev/null
+++ b/tests/expand/unsafe_unpin/tuple_struct.expanded.rs
@@ -0,0 +1,86 @@
+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(clippy::unknown_clippy_lints)]
+#[allow(clippy::pattern_type_mismatch)]
+#[allow(clippy::redundant_pub_crate)]
+#[allow(clippy::used_underscore_binding)]
+const _: () = {
+    #[allow(box_pointers)]
+    #[allow(deprecated)]
+    #[allow(explicit_outlives_requirements)]
+    #[allow(single_use_lifetimes)]
+    #[allow(unreachable_pub)]
+    #[allow(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::mut_mut)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __TupleStructProjection<'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(clippy::unknown_clippy_lints)]
+    #[allow(clippy::pattern_type_mismatch)]
+    #[allow(clippy::redundant_pub_crate)]
+    #[allow(dead_code)]
+    #[allow(clippy::ref_option_ref)]
+    #[allow(clippy::type_repetition_in_bounds)]
+    struct __TupleStructProjectionRef<'pin, T, U>(
+        ::pin_project::__private::Pin<&'pin (T)>,
+        &'pin (U),
+    )
+    where
+        TupleStruct<T, U>: 'pin;
+    impl<T, U> TupleStruct<T, U> {
+        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(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(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
index 0000000..964617a
--- /dev/null
+++ b/tests/expand/unsafe_unpin/tuple_struct.rs
@@ -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
index 0000000..adf8dde
--- /dev/null
+++ b/tests/expandtest.rs
@@ -0,0 +1,41 @@
+#![cfg(not(miri))]
+#![warn(rust_2018_idioms, single_use_lifetimes)]
+
+use std::{
+    env,
+    process::{Command, ExitStatus, Stdio},
+};
+
+#[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"]) || !has_command(&[cargo, "fmt"]) {
+        if is_ci {
+            panic!("expandtest requires rustfmt and cargo-expand")
+        }
+        return;
+    }
+
+    let path = "tests/expand/*/*.rs";
+    if is_ci {
+        macrotest::expand_without_refresh(path);
+    } else {
+        env::set_var("MACROTEST", "overwrite");
+        macrotest::expand(path);
+    }
+}
+
+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/lint.rs b/tests/lint.rs
index b577e0e..527c533 100644
--- a/tests/lint.rs
+++ b/tests/lint.rs
@@ -10,6 +10,7 @@
     explicit_outlives_requirements,
     macro_use_extern_crate,
     meta_variable_misuse,
+    missing_abi,
     missing_copy_implementations,
     missing_crate_level_docs,
     missing_debug_implementations,
@@ -27,7 +28,7 @@
     unused_results,
     variant_size_differences
 )]
-// absolute_paths_not_starting_with_crate, anonymous_parameters, keyword_idents, pointer_structural_match: forbidden as a part of future_incompatible
+// absolute_paths_not_starting_with_crate, anonymous_parameters, keyword_idents, pointer_structural_match, semicolon_in_expressions_from_macros: forbidden as a part of future_incompatible
 // missing_doc_code_examples, private_doc_tests, invalid_html_tags: warned as a part of rustdoc
 // unsafe_block_in_unsafe_fn: unstable
 // unsafe_code: checked in forbid_unsafe module
@@ -36,11 +37,10 @@
 #![warn(clippy::all, clippy::pedantic, clippy::nursery)]
 #![warn(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)] // TODO
 
 // Check interoperability with rustc and clippy lints.
 
-mod auxiliary;
-
 pub mod basic {
     include!("include/basic.rs");
 
@@ -543,6 +543,123 @@
     }
 }
 
+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;
 
@@ -652,7 +769,7 @@
     #[allow(single_use_lifetimes)] // for the type itself: https://github.com/rust-lang/rust/issues/55058
     #[pin_project(project_replace)]
     #[derive(Debug)]
-    pub struct HRTB<'pin___, T>
+    pub struct Hrtb<'pin___, T>
     where
         for<'pin> &'pin T: Unpin,
         T: for<'pin> Trait<'pin>,
@@ -675,7 +792,7 @@
                 #[allow(single_use_lifetimes)] // for the type itself: https://github.com/rust-lang/rust/issues/55058
                 #[pin_project(project_replace)]
                 #[derive(Debug)]
-                pub struct HRTB<'pin___, T>
+                pub struct Hrtb<'pin___, T>
                 where
                     for<'pin> &'pin T: Unpin,
                     T: for<'pin> Trait<'pin>,
@@ -1023,17 +1140,24 @@
     }
 }
 
-// Run `./dev.sh +$toolchain test --test lint` to update this.
-#[cfg(not(miri))]
-#[allow(clippy::restriction)]
-#[rustversion::attr(before(2020-12-25), ignore)] // Note: This date is commit-date and the day before the toolchain date.
-#[test]
-fn check_lint_list() {
-    use auxiliary::assert_diff;
-    use std::{env, process::Command, str};
+pub mod clippy_ref_option_ref {
+    use pin_project::pin_project;
 
-    let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
-    let output = Command::new(rustc).args(&["-W", "help"]).output().unwrap();
-    let new = str::from_utf8(&output.stdout).unwrap();
-    assert_diff("tests/lint.txt", new);
+    #[pin_project]
+    #[derive(Debug)]
+    pub struct Struct<'a> {
+        #[pin]
+        pub _pinned: Option<&'a ()>,
+        pub _unpinned: Option<&'a ()>,
+    }
+
+    #[pin_project(project = EnumProj, project_ref = EnumProjRef)]
+    #[derive(Debug)]
+    pub enum Enum<'a> {
+        Struct {
+            #[pin]
+            _pinned: Option<&'a ()>,
+            _unpinned: Option<&'a ()>,
+        },
+    }
 }
diff --git a/tests/lint.txt b/tests/lint.txt
deleted file mode 100644
index 8983ad7..0000000
--- a/tests/lint.txt
+++ /dev/null
@@ -1,157 +0,0 @@
-
-Available lint options:
-    -W <foo>           Warn about <foo>
-    -A <foo>           Allow <foo>
-    -D <foo>           Deny <foo>
-    -F <foo>           Forbid <foo> (deny <foo> and all attempts to override)
-
-
-Lint checks provided by rustc:
-
-                                                       name  default  meaning
-                                                       ----  -------  -------
-                     absolute-paths-not-starting-with-crate  allow    fully qualified paths that start with a module name instead of `crate`, `self`, or an extern crate name
-                                       anonymous-parameters  allow    detects anonymous parameters
-                                               box-pointers  allow    use of owned (Box type) heap memory
-                                       deprecated-in-future  allow    detects use of items that will be deprecated in a future version
-                                  elided-lifetimes-in-paths  allow    hidden lifetime parameters in types are deprecated
-                             explicit-outlives-requirements  allow    outlives requirements can be inferred
-                                          invalid-html-tags  allow    detects invalid HTML tags in doc comments
-                                             keyword-idents  allow    detects edition keywords being used as an identifier
-                                     macro-use-extern-crate  allow    the `#[macro_use]` attribute is now deprecated in favor of using macros via the module system
-                                       meta-variable-misuse  allow    possible meta-variable misuse at macro definition
-                               missing-copy-implementations  allow    detects potentially-forgotten implementations of `Copy`
-                                   missing-crate-level-docs  allow    detects crates with no crate-level documentation
-                              missing-debug-implementations  allow    detects missing implementations of Debug
-                                               missing-docs  allow    detects missing documentation for public members
-                                  missing-doc-code-examples  allow    detects publicly-exported items without code samples in their documentation
-                                           non-ascii-idents  allow    detects non-ASCII identifiers
-                                   pointer-structural-match  allow    pointers are not structural-match
-                                          private-doc-tests  allow    detects code samples in docs of private items not documented by rustdoc
-                                       single-use-lifetimes  allow    detects lifetime parameters that are only used once
-                                              trivial-casts  allow    detects trivial casts which could be removed
-                                      trivial-numeric-casts  allow    detects trivial casts of numeric types which could be removed
-                                       unaligned-references  allow    detects unaligned references to fields of packed structs
-                                            unreachable-pub  allow    `pub` items not reachable from crate root
-                                                unsafe-code  allow    usage of `unsafe` code
-                                     unsafe-op-in-unsafe-fn  allow    unsafe operations in unsafe functions without an explicit unsafe block are deprecated
-                                          unstable-features  allow    enabling unstable features (deprecated. do not use)
-                                  unused-crate-dependencies  allow    crate dependencies that are never used
-                                       unused-extern-crates  allow    extern crates that are never used
-                                       unused-import-braces  allow    unnecessary braces around an imported item
-                                           unused-lifetimes  allow    detects lifetime parameters that are never used
-                                      unused-qualifications  allow    detects unnecessarily qualified names
-                                             unused-results  allow    unused result of an expression in a statement
-                                   variant-size-differences  allow    detects enums with widely varying variant sizes
-                                            array-into-iter  warn     detects calling `into_iter` on arrays
-                                           asm-sub-register  warn     using only a subset of a register for inline asm inputs
-                                         bare-trait-objects  warn     suggest using `dyn Trait` for trait objects
-                                 bindings-with-variant-name  warn     detects pattern bindings with the same name as one of the matched variants
-                                     broken-intra-doc-links  warn     failures in resolving intra-doc link targets
-                                       cenum-impl-drop-cast  warn     a C-like enum implementing Drop is cast
-                               clashing-extern-declarations  warn     detects when an extern fn has been declared with the same name but different types
-                                       coherence-leak-check  warn     distinct impls distinguished only by the leak-check code
-                                          confusable-idents  warn     detects visually confusable pairs between identifiers
-                                const-evaluatable-unchecked  warn     detects a generic constant is used in a type without a emitting a warning
-                                        const-item-mutation  warn     detects attempts to mutate a `const` item
-                                                  dead-code  warn     detect unused, unexported items
-                                                 deprecated  warn     detects use of deprecated items
-                                                drop-bounds  warn     bounds of the form `T: Drop` are useless
-                          ellipsis-inclusive-range-patterns  warn     `...` range patterns are deprecated
-                              exported-private-dependencies  warn     public interface leaks type from a private dependency
-                                   function-item-references  warn     suggest casting to a function pointer when attempting to take references to function items
-                     illegal-floating-point-literal-pattern  warn     floating-point literals cannot be used in patterns
-                                            improper-ctypes  warn     proper use of libc types in foreign modules
-                                improper-ctypes-definitions  warn     proper use of libc types in foreign item definitions
-                                        incomplete-features  warn     incomplete features that may function improperly in some or all cases
-                                  indirect-structural-match  warn     constant used in pattern contains value of non-structural-match type in a field or a variant
-                                         inline-no-sanitize  warn     detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]`
-                               invalid-codeblock-attributes  warn     codeblock attribute looks a lot like a known one
-                                              invalid-value  warn     an invalid value is being created (such as a NULL reference)
-                                   irrefutable-let-patterns  warn     detects irrefutable patterns in if-let and while-let statements
-                              late-bound-lifetime-arguments  warn     detects generic lifetime arguments in path segments with late bound lifetime parameters
-                                   mixed-script-confusables  warn     detects Unicode scripts whose mixed script confusables codepoints are solely used
-                        mutable-borrow-reservation-conflict  warn     reservation of a two-phased borrow conflicts with other shared borrows
-                                nontrivial-structural-match  warn     constant used in pattern of non-structural-match type and the constant's initializer expression contains values of non-structural-match types
-                                              non-autolinks  warn     detects URLs that could be written using only angle brackets
-                                       non-camel-case-types  warn     types, variants, traits and type parameters should have camel case names
-                               non-shorthand-field-patterns  warn     using `Struct { x: x }` instead of `Struct { x }` in a pattern
-                                             non-snake-case  warn     variables, methods, functions, lifetime parameters and modules should have snake case names
-                                     non-upper-case-globals  warn     static constants should have uppercase identifiers
-                                    no-mangle-generic-items  warn     generic items must be mangled
-                                overlapping-range-endpoints  warn     detects range patterns with overlapping endpoints
-                                                  panic-fmt  warn     detect braces in single-argument panic!() invocations
-                                            path-statements  warn     path statements with no effect
-                                    private-intra-doc-links  warn     linking from a public item to a private one
-                                          private-in-public  warn     detect private items in public interfaces not caught by the old implementation
-                      proc-macro-derive-resolution-fallback  warn     detects proc macro derives using inaccessible names from parent modules
-                                       redundant-semicolons  warn     detects unnecessary trailing semicolons
-                                  renamed-and-removed-lints  warn     lints that have been renamed or removed
-                                        safe-packed-borrows  warn     safe borrows of fields of packed structs were erroneously allowed
-                                            stable-features  warn     stable features found in `#[feature]` directive
-                                   temporary-cstring-as-ptr  warn     detects getting the inner pointer of a temporary `CString`
-                                             trivial-bounds  warn     these bounds don't depend on an type parameters
-                                          type-alias-bounds  warn     bounds in type aliases are not enforced
-                                   tyvar-behind-raw-pointer  warn     raw pointer to an inference variable
-                                        uncommon-codepoints  warn     detects uncommon Unicode codepoints in identifiers
-                                    unconditional-recursion  warn     functions that cannot return without calling themselves
-                                         uninhabited-static  warn     uninhabited static
-                                              unknown-lints  warn     unrecognized lint attribute
-                                      unnameable-test-items  warn     detects an item that cannot be named being marked as `#[test_case]`
-                                           unreachable-code  warn     detects unreachable code paths
-                                       unreachable-patterns  warn     detects unreachable patterns
-                                   unstable-name-collisions  warn     detects name collision with an existing but unstable method
-                                unsupported-naked-functions  warn     unsupported naked function definitions
-                                          unused-allocation  warn     detects unnecessary allocations that can be eliminated
-                                         unused-assignments  warn     detect assignments that will never be read
-                                          unused-attributes  warn     detects attributes that were not used by the compiler
-                                              unused-braces  warn     unnecessary braces around an expression
-                                         unused-comparisons  warn     comparisons made useless by limits of the types involved
-                                        unused-doc-comments  warn     detects doc comments that aren't used by rustdoc
-                                            unused-features  warn     unused features found in crate-level `#[feature]` directives
-                                             unused-imports  warn     imports that are never used
-                                              unused-labels  warn     detects labels that are never used
-                                              unused-macros  warn     detects macros that were not used
-                                            unused-must-use  warn     unused result of a type flagged as `#[must_use]`
-                                                 unused-mut  warn     detect mut variables which don't need to be mutable
-                                              unused-parens  warn     `if`, `match`, `while` and `return` do not need parentheses
-                                              unused-unsafe  warn     unnecessary use of an `unsafe` block
-                                           unused-variables  warn     detect variables which are not used in any way
-                                                   warnings  warn     mass-change the level for lints which produce warnings
-                                where-clauses-object-safety  warn     checks the object safety of where clauses
-                                                 while-true  warn     suggest using `loop { }` instead of `while true { }`
-                                 ambiguous-associated-items  deny     ambiguous associated items
-                                        arithmetic-overflow  deny     arithmetic operation overflows
-                                     conflicting-repr-hints  deny     conflicts between `#[repr(..)]` hints that were previously accepted and used in practice
-                                                  const-err  deny     constant evaluation detected erroneous expression
-                                 ill-formed-attribute-input  deny     ill-formed attribute inputs that were previously accepted and used in practice
-                                         incomplete-include  deny     trailing content in included file
-                                 invalid-type-param-default  deny     type parameter default erroneously allowed in invalid location
-    macro-expanded-macro-exports-accessed-by-absolute-paths  deny     macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
-                                 missing-fragment-specifier  deny     detects missing fragment specifiers in unused `macro_rules!` patterns
-                                         mutable-transmutes  deny     mutating transmuted &mut T from &T may cause undefined behavior
-                                      no-mangle-const-items  deny     const items will not have their symbols exported
-                              order-dependent-trait-objects  deny     trait-object types were treated as different depending on marker-trait order
-                                       overflowing-literals  deny     literal out of range for its type
-                               patterns-in-fns-without-body  deny     patterns in functions without body were erroneously allowed
-                            pub-use-of-private-extern-crate  deny     detect public re-exports of private extern crates
-                                              soft-unstable  deny     a feature gate that doesn't break dependent crates
-                                        unconditional-panic  deny     operation will cause a panic at runtime
-                                        unknown-crate-types  deny     unknown crate type found in `#[crate_type]` directive
-                                         useless-deprecated  deny     detects deprecation attributes with no effect
-
-
-Lint groups provided by rustc:
-
-                       name  sub-lints
-                       ----  ---------
-                   warnings  all lints that are set to issue warnings
-        future-incompatible  keyword-idents, anonymous-parameters, illegal-floating-point-literal-pattern, private-in-public, pub-use-of-private-extern-crate, invalid-type-param-default, safe-packed-borrows, patterns-in-fns-without-body, missing-fragment-specifier, late-bound-lifetime-arguments, order-dependent-trait-objects, coherence-leak-check, tyvar-behind-raw-pointer, absolute-paths-not-starting-with-crate, unstable-name-collisions, where-clauses-object-safety, proc-macro-derive-resolution-fallback, macro-expanded-macro-exports-accessed-by-absolute-paths, ill-formed-attribute-input, conflicting-repr-hints, ambiguous-associated-items, mutable-borrow-reservation-conflict, indirect-structural-match, pointer-structural-match, nontrivial-structural-match, soft-unstable, cenum-impl-drop-cast, const-evaluatable-unchecked, uninhabited-static, unsupported-naked-functions, array-into-iter
-          nonstandard-style  non-camel-case-types, non-snake-case, non-upper-case-globals
-    rust-2018-compatibility  keyword-idents, anonymous-parameters, tyvar-behind-raw-pointer, absolute-paths-not-starting-with-crate
-           rust-2018-idioms  bare-trait-objects, unused-extern-crates, ellipsis-inclusive-range-patterns, elided-lifetimes-in-paths, explicit-outlives-requirements
-                    rustdoc  non-autolinks, broken-intra-doc-links, private-intra-doc-links, invalid-codeblock-attributes, missing-doc-code-examples, private-doc-tests, invalid-html-tags
-                     unused  unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons
-
-
-Lint tools like Clippy can provide additional lints and lint groups.
diff --git a/tests/pin_project.rs b/tests/pin_project.rs
index 17dbd2a..c6aaf94 100644
--- a/tests/pin_project.rs
+++ b/tests/pin_project.rs
@@ -4,13 +4,14 @@
 #[macro_use]
 mod auxiliary;
 
-use pin_project::{pin_project, pinned_drop, UnsafeUnpin};
 use std::{
     marker::{PhantomData, PhantomPinned},
     panic,
     pin::Pin,
 };
 
+use pin_project::{pin_project, pinned_drop, UnsafeUnpin};
+
 #[test]
 fn projection() {
     #[pin_project(
@@ -336,7 +337,7 @@
 
     #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
     #[pin_project(project_replace)]
-    pub struct HRTB<'pin___, T>
+    pub struct Hrtb<'pin___, T>
     where
         for<'pin> &'pin T: Unpin,
         T: for<'pin> Trait<'pin>,
diff --git a/tests/pinned_drop.rs b/tests/pinned_drop.rs
index 78b73dc..9e7287d 100644
--- a/tests/pinned_drop.rs
+++ b/tests/pinned_drop.rs
@@ -1,8 +1,9 @@
 #![warn(rust_2018_idioms, single_use_lifetimes)]
 
-use pin_project::{pin_project, pinned_drop};
 use std::pin::Pin;
 
+use pin_project::{pin_project, pinned_drop};
+
 #[test]
 fn safe_project() {
     #[pin_project(PinnedDrop)]
diff --git a/tests/proper_unpin.rs b/tests/proper_unpin.rs
index 8873572..0ba3ce3 100644
--- a/tests/proper_unpin.rs
+++ b/tests/proper_unpin.rs
@@ -5,9 +5,10 @@
 mod auxiliary;
 
 pub mod default {
-    use pin_project::pin_project;
     use std::marker::PhantomPinned;
 
+    use pin_project::pin_project;
+
     struct Inner<T> {
         f: T,
     }
@@ -60,9 +61,10 @@
 }
 
 pub mod cfg {
-    use pin_project::pin_project;
     use std::marker::PhantomPinned;
 
+    use pin_project::pin_project;
+
     #[pin_project]
     struct Foo<T> {
         #[cfg(any())]
@@ -88,9 +90,10 @@
 }
 
 pub mod cfg_attr {
-    use pin_project::pin_project;
     use std::marker::PhantomPinned;
 
+    use pin_project::pin_project;
+
     #[cfg_attr(any(), pin_project)]
     struct Foo<T> {
         f: T,
@@ -111,9 +114,10 @@
 
 // pin_project(!Unpin)
 pub mod not_unpin {
-    use pin_project::pin_project;
     use std::marker::PhantomPinned;
 
+    use pin_project::pin_project;
+
     struct Inner<T> {
         f: T,
     }
diff --git a/tests/ui/cfg/packed_sneaky-span-issue-1.rs b/tests/ui/cfg/packed_sneaky-span-issue-1.rs
index 8455d07..42f57b5 100644
--- a/tests/ui/cfg/packed_sneaky-span-issue-1.rs
+++ b/tests/ui/cfg/packed_sneaky-span-issue-1.rs
@@ -1,12 +1,10 @@
 use auxiliary_macro::hidden_repr;
 use pin_project::pin_project;
 
-//~ ERROR may not be used on #[repr(packed)] types
-// span is lost.
-// Refs: https://github.com/rust-lang/rust/issues/43081
 #[pin_project]
 #[hidden_repr(packed)]
 struct S {
+    //~^ ERROR may not be used on #[repr(packed)] types
     #[cfg(not(any()))]
     #[pin]
     f: u32,
diff --git a/tests/ui/cfg/packed_sneaky-span-issue-1.stderr b/tests/ui/cfg/packed_sneaky-span-issue-1.stderr
index f4d7dee..abe3ecd 100644
--- a/tests/ui/cfg/packed_sneaky-span-issue-1.stderr
+++ b/tests/ui/cfg/packed_sneaky-span-issue-1.stderr
@@ -1 +1,11 @@
 error: #[pin_project] attribute may not be used on #[repr(packed)] types
+  --> $DIR/packed_sneaky-span-issue-1.rs:6:1
+   |
+6  | / struct S {
+7  | |     //~^ ERROR may not be used on #[repr(packed)] types
+8  | |     #[cfg(not(any()))]
+9  | |     #[pin]
+...  |
+13 | |     f: u8,
+14 | | }
+   | |_^
diff --git a/tests/ui/cfg/packed_sneaky-span-issue-2.rs b/tests/ui/cfg/packed_sneaky-span-issue-2.rs
index 01706ee..948d72c 100644
--- a/tests/ui/cfg/packed_sneaky-span-issue-2.rs
+++ b/tests/ui/cfg/packed_sneaky-span-issue-2.rs
@@ -1,12 +1,10 @@
 use auxiliary_macro::hidden_repr;
 use pin_project::pin_project;
 
-//~ ERROR may not be used on #[repr(packed)] types
-// span is lost.
-// Refs: https://github.com/rust-lang/rust/issues/43081
 #[pin_project]
 #[hidden_repr(packed)]
 struct S {
+    //~^ ERROR may not be used on #[repr(packed)] types
     #[cfg(any())]
     #[pin]
     f: u32,
diff --git a/tests/ui/cfg/packed_sneaky-span-issue-2.stderr b/tests/ui/cfg/packed_sneaky-span-issue-2.stderr
index f4d7dee..a957ceb 100644
--- a/tests/ui/cfg/packed_sneaky-span-issue-2.stderr
+++ b/tests/ui/cfg/packed_sneaky-span-issue-2.stderr
@@ -1 +1,11 @@
 error: #[pin_project] attribute may not be used on #[repr(packed)] types
+  --> $DIR/packed_sneaky-span-issue-2.rs:6:1
+   |
+6  | / struct S {
+7  | |     //~^ ERROR may not be used on #[repr(packed)] types
+8  | |     #[cfg(any())]
+9  | |     #[pin]
+...  |
+13 | |     f: u8,
+14 | | }
+   | |_^
diff --git a/tests/ui/cfg/unsupported.rs b/tests/ui/cfg/unsupported.rs
index c450f6f..b950d4b 100644
--- a/tests/ui/cfg/unsupported.rs
+++ b/tests/ui/cfg/unsupported.rs
@@ -1,10 +1,8 @@
 use pin_project::pin_project;
 
-//~ ERROR may not be used on structs with zero fields
-// span is lost.
-// Refs: https://github.com/rust-lang/rust/issues/43081
 #[pin_project]
 struct S {
+    //~^ ERROR may not be used on structs with zero fields
     #[cfg(any())]
     #[pin]
     f: u8,
diff --git a/tests/ui/cfg/unsupported.stderr b/tests/ui/cfg/unsupported.stderr
index 0ee8676..b3bd1ae 100644
--- a/tests/ui/cfg/unsupported.stderr
+++ b/tests/ui/cfg/unsupported.stderr
@@ -1 +1,10 @@
 error: #[pin_project] attribute may not be used on structs with zero fields
+ --> $DIR/unsupported.rs:4:1
+  |
+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/pin_project/project_replace_unsized.stderr b/tests/ui/pin_project/project_replace_unsized.stderr
index e40db5f..26e416a 100644
--- a/tests/ui/pin_project/project_replace_unsized.stderr
+++ b/tests/ui/pin_project/project_replace_unsized.stderr
@@ -14,14 +14,6 @@
   |               ^
 
 error[E0277]: the size for values of type `T` cannot be known at compilation time
-   --> $DIR/project_replace_unsized.rs:5:5
-    |
-4   | struct Struct<T: ?Sized> {
-    |               - this type parameter needs to be `Sized`
-5   |     f: T,
-    |     ^ doesn't have a size known at compile-time
-
-error[E0277]: the size for values of type `T` cannot be known at compilation time
  --> $DIR/project_replace_unsized.rs:3:1
   |
 3 | #[pin_project(project_replace)] //~ ERROR E0277
@@ -29,11 +21,19 @@
 4 | struct Struct<T: ?Sized> {
   |               - this type parameter needs to be `Sized`
   |
-  = note: required because it appears within the type `__StructProjectionOwned<T>`
-  = note: structs must have a statically known size to be initialized
+  = note: required because it appears within the type `Struct<T>`
+  = note: required by `UnsafeOverwriteGuard`
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the size for values of type `T` cannot be known at compilation time
+   --> $DIR/project_replace_unsized.rs:5:5
+    |
+4   | struct Struct<T: ?Sized> {
+    |               - this type parameter needs to be `Sized`
+5   |     f: T,
+    |     ^ doesn't have a size known at compile-time
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
  --> $DIR/project_replace_unsized.rs:8:15
   |
 8 | #[pin_project(project_replace)] //~ ERROR E0277
@@ -49,14 +49,16 @@
   |               ^
 
 error[E0277]: the size for values of type `T` cannot be known at compilation time
-   --> $DIR/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 `Sized`
-    |
-    = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
+ --> $DIR/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 `Sized`
+  |
+  = note: required because it appears within the type `TupleStruct<T>`
+  = note: required by `UnsafeOverwriteGuard`
+  = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the size for values of type `T` cannot be known at compilation time
  --> $DIR/project_replace_unsized.rs:9:8
diff --git a/tests/ui/pin_project/project_replace_unsized_fn_params.stderr b/tests/ui/pin_project/project_replace_unsized_fn_params.stderr
index 622d12f..f0f9573 100644
--- a/tests/ui/pin_project/project_replace_unsized_fn_params.stderr
+++ b/tests/ui/pin_project/project_replace_unsized_fn_params.stderr
@@ -11,14 +11,6 @@
   = note: the return type of a function must have a statically known size
 
 error[E0277]: the size for values of type `T` cannot be known at compilation time
-   --> $DIR/project_replace_unsized_fn_params.rs:7:5
-    |
-6   | struct Struct<T: ?Sized> {
-    |               - this type parameter needs to be `Sized`
-7   |     f: T,
-    |     ^ doesn't have a size known at compile-time
-
-error[E0277]: the size for values of type `T` cannot be known at compilation time
  --> $DIR/project_replace_unsized_fn_params.rs:5:1
   |
 5 | #[pin_project(project_replace)] //~ ERROR E0277
@@ -26,11 +18,19 @@
 6 | struct Struct<T: ?Sized> {
   |               - this type parameter needs to be `Sized`
   |
-  = note: required because it appears within the type `__StructProjectionOwned<T>`
-  = note: structs must have a statically known size to be initialized
+  = note: required because it appears within the type `Struct<T>`
+  = note: required by `UnsafeOverwriteGuard`
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the size for values of type `T` cannot be known at compilation time
+   --> $DIR/project_replace_unsized_fn_params.rs:7:5
+    |
+6   | struct Struct<T: ?Sized> {
+    |               - this type parameter needs to be `Sized`
+7   |     f: T,
+    |     ^ doesn't have a size known at compile-time
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
   --> $DIR/project_replace_unsized_fn_params.rs:11:8
    |
 11 | struct TupleStruct<T: ?Sized>(T);
@@ -43,11 +43,13 @@
    = note: the return type of a function must have a statically known size
 
 error[E0277]: the size for values of type `T` cannot be known at compilation time
-   --> $DIR/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 `Sized`
-    |
-    = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  --> $DIR/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 `Sized`
+   |
+   = note: required because it appears within the type `TupleStruct<T>`
+   = note: required by `UnsafeOverwriteGuard`
+   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/unstable-features/marker_trait_attr-feature-gate.rs b/tests/ui/unstable-features/marker_trait_attr-feature-gate.rs
index 8860f4f..127cd1a 100644
--- a/tests/ui/unstable-features/marker_trait_attr-feature-gate.rs
+++ b/tests/ui/unstable-features/marker_trait_attr-feature-gate.rs
@@ -1,4 +1,4 @@
-// NB: If you change this test, change 'marker_trait_attr.rs' at the same time.
+// Note: If you change this test, change 'marker_trait_attr.rs' at the same time.
 
 use pin_project::pin_project;
 use std::marker::PhantomPinned;
diff --git a/tests/ui/unstable-features/marker_trait_attr.rs b/tests/ui/unstable-features/marker_trait_attr.rs
index a6ca357..d6eab21 100644
--- a/tests/ui/unstable-features/marker_trait_attr.rs
+++ b/tests/ui/unstable-features/marker_trait_attr.rs
@@ -1,4 +1,4 @@
-// NB: If you change this test, change 'marker_trait_attr-feature-gate.rs' at the same time.
+// 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
diff --git a/tests/ui/unstable-features/overlapping_marker_traits-feature-gate.rs b/tests/ui/unstable-features/overlapping_marker_traits-feature-gate.rs
index 3af3cf0..9d1b8b8 100644
--- a/tests/ui/unstable-features/overlapping_marker_traits-feature-gate.rs
+++ b/tests/ui/unstable-features/overlapping_marker_traits-feature-gate.rs
@@ -1,4 +1,4 @@
-// NB: If you change this test, change 'overlapping_marker_traits.rs' at the same time.
+// Note: If you change this test, change 'overlapping_marker_traits.rs' at the same time.
 
 use pin_project::pin_project;
 use std::marker::PhantomPinned;
diff --git a/tests/ui/unstable-features/overlapping_marker_traits.rs b/tests/ui/unstable-features/overlapping_marker_traits.rs
index c897d1c..0e0cddd 100644
--- a/tests/ui/unstable-features/overlapping_marker_traits.rs
+++ b/tests/ui/unstable-features/overlapping_marker_traits.rs
@@ -1,4 +1,4 @@
-// NB: If you change this test, change 'overlapping_marker_traits-feature-gate.rs' at the same time.
+// 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).
diff --git a/tests/ui/unstable-features/trivial_bounds-bug.rs b/tests/ui/unstable-features/trivial_bounds-bug.rs
index 2ec4960..5e821c4 100644
--- a/tests/ui/unstable-features/trivial_bounds-bug.rs
+++ b/tests/ui/unstable-features/trivial_bounds-bug.rs
@@ -1,4 +1,4 @@
-// NB: If you change this test, change 'trivial_bounds-feature-gate.rs' at the same time.
+// 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
diff --git a/tests/ui/unstable-features/trivial_bounds-feature-gate.rs b/tests/ui/unstable-features/trivial_bounds-feature-gate.rs
index ccdb182..f8467b0 100644
--- a/tests/ui/unstable-features/trivial_bounds-feature-gate.rs
+++ b/tests/ui/unstable-features/trivial_bounds-feature-gate.rs
@@ -1,4 +1,4 @@
-// NB: If you change this test, change 'trivial_bounds.rs' at the same time.
+// Note: If you change this test, change 'trivial_bounds.rs' at the same time.
 
 mod phantom_pinned {
     use std::marker::{PhantomData, PhantomPinned};
diff --git a/tests/ui/unstable-features/trivial_bounds.rs b/tests/ui/unstable-features/trivial_bounds.rs
index 680effe..2323bab 100644
--- a/tests/ui/unstable-features/trivial_bounds.rs
+++ b/tests/ui/unstable-features/trivial_bounds.rs
@@ -1,4 +1,4 @@
-// NB: If you change this test, change 'trivial_bounds-feature-gate.rs' at the same time.
+// 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
diff --git a/tests/unsafe_unpin.rs b/tests/unsafe_unpin.rs
index 1bd6c0b..8b6411c 100644
--- a/tests/unsafe_unpin.rs
+++ b/tests/unsafe_unpin.rs
@@ -4,9 +4,10 @@
 #[macro_use]
 mod auxiliary;
 
-use pin_project::{pin_project, UnsafeUnpin};
 use std::marker::PhantomPinned;
 
+use pin_project::{pin_project, UnsafeUnpin};
+
 #[pin_project(UnsafeUnpin)]
 pub struct Blah<T, U> {
     f1: U,