From c404270db6d632c9f7f404f549a7e9bc5f3e2113 Mon Sep 17 00:00:00 2001 From: Roy7Kim Date: Mon, 20 Mar 2023 13:35:04 +0900 Subject: [PATCH 1/1] Import pin-project 1.0.12 --- .cargo_vcs_info.json | 6 + CHANGELOG.md | 758 +++++++++++++ Cargo.lock | 222 ++++ Cargo.toml | 54 + Cargo.toml.orig | 39 + LICENSE-APACHE | 177 +++ LICENSE-MIT | 23 + README.md | 99 ++ examples/README.md | 39 + examples/enum-default-expanded.rs | 101 ++ examples/enum-default.rs | 13 + examples/not_unpin-expanded.rs | 125 ++ examples/not_unpin.rs | 17 + examples/pinned_drop-expanded.rs | 154 +++ examples/pinned_drop.rs | 23 + examples/project_replace-expanded.rs | 156 +++ examples/project_replace.rs | 14 + examples/struct-default-expanded.rs | 155 +++ examples/struct-default.rs | 14 + examples/unsafe_unpin-expanded.rs | 107 ++ examples/unsafe_unpin.rs | 16 + src/lib.rs | 315 ++++++ tests/README.md | 44 + tests/auxiliary/mod.rs | 12 + tests/cfg.rs | 184 +++ tests/compiletest.rs | 16 + tests/drop_order.rs | 162 +++ tests/expand/default/enum.expanded.rs | 145 +++ tests/expand/default/enum.rs | 14 + tests/expand/default/struct.expanded.rs | 104 ++ tests/expand/default/struct.rs | 10 + tests/expand/default/tuple_struct.expanded.rs | 98 ++ tests/expand/default/tuple_struct.rs | 6 + tests/expand/multifields/enum.expanded.rs | 268 +++++ tests/expand/multifields/enum.rs | 17 + tests/expand/multifields/struct.expanded.rs | 155 +++ tests/expand/multifields/struct.rs | 13 + tests/expand/multifields/tuple_struct.expanded.rs | 145 +++ tests/expand/multifields/tuple_struct.rs | 6 + tests/expand/naming/enum-all.expanded.rs | 204 ++++ tests/expand/naming/enum-all.rs | 14 + tests/expand/naming/enum-mut.expanded.rs | 99 ++ tests/expand/naming/enum-mut.rs | 14 + tests/expand/naming/enum-none.expanded.rs | 56 + tests/expand/naming/enum-none.rs | 14 + tests/expand/naming/enum-own.expanded.rs | 119 ++ tests/expand/naming/enum-own.rs | 14 + tests/expand/naming/enum-ref.expanded.rs | 100 ++ tests/expand/naming/enum-ref.rs | 14 + tests/expand/naming/struct-all.expanded.rs | 163 +++ tests/expand/naming/struct-all.rs | 10 + tests/expand/naming/struct-mut.expanded.rs | 114 ++ tests/expand/naming/struct-mut.rs | 10 + tests/expand/naming/struct-none.expanded.rs | 104 ++ tests/expand/naming/struct-none.rs | 10 + tests/expand/naming/struct-own.expanded.rs | 143 +++ tests/expand/naming/struct-own.rs | 10 + tests/expand/naming/struct-ref.expanded.rs | 114 ++ tests/expand/naming/struct-ref.rs | 10 + tests/expand/naming/tuple_struct-all.expanded.rs | 148 +++ tests/expand/naming/tuple_struct-all.rs | 6 + tests/expand/naming/tuple_struct-mut.expanded.rs | 105 ++ tests/expand/naming/tuple_struct-mut.rs | 6 + tests/expand/naming/tuple_struct-none.expanded.rs | 98 ++ tests/expand/naming/tuple_struct-none.rs | 6 + tests/expand/naming/tuple_struct-own.expanded.rs | 134 +++ tests/expand/naming/tuple_struct-own.rs | 6 + tests/expand/naming/tuple_struct-ref.expanded.rs | 105 ++ tests/expand/naming/tuple_struct-ref.rs | 6 + tests/expand/not_unpin/enum.expanded.rs | 139 +++ tests/expand/not_unpin/enum.rs | 14 + tests/expand/not_unpin/struct.expanded.rs | 99 ++ tests/expand/not_unpin/struct.rs | 10 + tests/expand/not_unpin/tuple_struct.expanded.rs | 93 ++ tests/expand/not_unpin/tuple_struct.rs | 6 + tests/expand/pinned_drop/enum.expanded.rs | 157 +++ tests/expand/pinned_drop/enum.rs | 23 + tests/expand/pinned_drop/struct.expanded.rs | 116 ++ tests/expand/pinned_drop/struct.rs | 19 + tests/expand/pinned_drop/tuple_struct.expanded.rs | 110 ++ tests/expand/pinned_drop/tuple_struct.rs | 15 + tests/expand/project_replace/enum.expanded.rs | 119 ++ tests/expand/project_replace/enum.rs | 14 + tests/expand/project_replace/struct.expanded.rs | 133 +++ tests/expand/project_replace/struct.rs | 10 + .../project_replace/tuple_struct.expanded.rs | 127 +++ tests/expand/project_replace/tuple_struct.rs | 6 + tests/expand/pub/enum.expanded.rs | 145 +++ tests/expand/pub/enum.rs | 14 + tests/expand/pub/struct.expanded.rs | 104 ++ tests/expand/pub/struct.rs | 10 + tests/expand/pub/tuple_struct.expanded.rs | 98 ++ tests/expand/pub/tuple_struct.rs | 6 + tests/expand/unsafe_unpin/enum.expanded.rs | 129 +++ tests/expand/unsafe_unpin/enum.rs | 16 + tests/expand/unsafe_unpin/struct.expanded.rs | 89 ++ tests/expand/unsafe_unpin/struct.rs | 12 + tests/expand/unsafe_unpin/tuple_struct.expanded.rs | 83 ++ tests/expand/unsafe_unpin/tuple_struct.rs | 8 + tests/expandtest.rs | 43 + tests/include/basic-safe-part.rs | 193 ++++ tests/include/basic.rs | 17 + tests/lint.rs | 1190 ++++++++++++++++++++ tests/pin_project.rs | 887 +++++++++++++++ tests/pinned_drop.rs | 284 +++++ tests/proper_unpin.rs | 153 +++ tests/repr_packed.rs | 52 + tests/ui/cfg/cfg_attr-resolve.rs | 11 + tests/ui/cfg/cfg_attr-resolve.stderr | 5 + tests/ui/cfg/cfg_attr-type-mismatch.rs | 25 + tests/ui/cfg/cfg_attr-type-mismatch.stderr | 23 + tests/ui/cfg/packed_sneaky-span-issue-1.rs | 15 + tests/ui/cfg/packed_sneaky-span-issue-1.stderr | 5 + tests/ui/cfg/packed_sneaky-span-issue-2.rs | 15 + tests/ui/cfg/packed_sneaky-span-issue-2.stderr | 5 + tests/ui/cfg/packed_sneaky.rs | 12 + tests/ui/cfg/packed_sneaky.stderr | 5 + tests/ui/cfg/unsupported.rs | 11 + tests/ui/cfg/unsupported.stderr | 11 + tests/ui/not_unpin/conflict-unpin.rs | 30 + tests/ui/not_unpin/conflict-unpin.stderr | 26 + tests/ui/not_unpin/impl-unsafe-unpin.rs | 30 + tests/ui/not_unpin/impl-unsafe-unpin.stderr | 32 + tests/ui/pin_project/add-attr-to-struct.rs | 20 + tests/ui/pin_project/add-attr-to-struct.stderr | 15 + tests/ui/pin_project/add-pinned-field.rs | 23 + tests/ui/pin_project/add-pinned-field.stderr | 52 + tests/ui/pin_project/conflict-drop.rs | 32 + tests/ui/pin_project/conflict-drop.stderr | 19 + tests/ui/pin_project/conflict-unpin.rs | 37 + tests/ui/pin_project/conflict-unpin.stderr | 32 + tests/ui/pin_project/impl-unsafe-unpin.rs | 30 + tests/ui/pin_project/impl-unsafe-unpin.stderr | 32 + tests/ui/pin_project/import_unnamed.rs | 30 + tests/ui/pin_project/import_unnamed.stderr | 29 + tests/ui/pin_project/invalid.rs | 280 +++++ tests/ui/pin_project/invalid.stderr | 364 ++++++ tests/ui/pin_project/overlapping_unpin_struct.rs | 19 + .../ui/pin_project/overlapping_unpin_struct.stderr | 25 + tests/ui/pin_project/override-priv-mod.rs | 32 + tests/ui/pin_project/override-priv-mod.stderr | 10 + tests/ui/pin_project/packed-enum.rs | 24 + tests/ui/pin_project/packed-enum.stderr | 42 + tests/ui/pin_project/packed-name-value.rs | 27 + tests/ui/pin_project/packed-name-value.stderr | 23 + tests/ui/pin_project/packed.rs | 33 + tests/ui/pin_project/packed.stderr | 23 + tests/ui/pin_project/packed_sneaky-1.rs | 41 + tests/ui/pin_project/packed_sneaky-1.stderr | 25 + tests/ui/pin_project/packed_sneaky-2.rs | 12 + tests/ui/pin_project/packed_sneaky-2.stderr | 13 + tests/ui/pin_project/packed_sneaky-3.rs | 32 + tests/ui/pin_project/packed_sneaky-3.stderr | 32 + tests/ui/pin_project/packed_sneaky-4.rs | 15 + tests/ui/pin_project/packed_sneaky-4.stderr | 16 + tests/ui/pin_project/private_in_public-enum.rs | 23 + tests/ui/pin_project/private_in_public-enum.stderr | 17 + tests/ui/pin_project/project_replace_unsized.rs | 11 + .../ui/pin_project/project_replace_unsized.stderr | 118 ++ .../project_replace_unsized_fn_params.rs | 13 + .../project_replace_unsized_fn_params.stderr | 112 ++ tests/ui/pin_project/remove-attr-from-field.rs | 33 + tests/ui/pin_project/remove-attr-from-field.stderr | 21 + tests/ui/pin_project/remove-attr-from-struct.rs | 47 + .../ui/pin_project/remove-attr-from-struct.stderr | 107 ++ tests/ui/pin_project/safe_packed_borrows.rs | 26 + tests/ui/pin_project/safe_packed_borrows.stderr | 11 + tests/ui/pin_project/unaligned_references.rs | 21 + tests/ui/pin_project/unaligned_references.stderr | 26 + tests/ui/pin_project/unpin_sneaky.rs | 11 + tests/ui/pin_project/unpin_sneaky.stderr | 5 + tests/ui/pin_project/visibility.rs | 49 + tests/ui/pin_project/visibility.stderr | 39 + tests/ui/pinned_drop/call-drop-inner.rs | 17 + tests/ui/pinned_drop/call-drop-inner.stderr | 16 + tests/ui/pinned_drop/conditional-drop-impl.rs | 27 + tests/ui/pinned_drop/conditional-drop-impl.stderr | 28 + tests/ui/pinned_drop/forget-pinned-drop-impl.rs | 9 + .../ui/pinned_drop/forget-pinned-drop-impl.stderr | 5 + tests/ui/pinned_drop/invalid-self.rs | 14 + tests/ui/pinned_drop/invalid-self.stderr | 25 + tests/ui/pinned_drop/invalid.rs | 231 ++++ tests/ui/pinned_drop/invalid.stderr | 143 +++ tests/ui/pinned_drop/pinned-drop-no-attr-arg.rs | 17 + .../ui/pinned_drop/pinned-drop-no-attr-arg.stderr | 8 + tests/ui/pinned_drop/self.rs | 58 + tests/ui/pinned_drop/self.stderr | 62 + tests/ui/pinned_drop/unsafe-call.rs | 18 + tests/ui/pinned_drop/unsafe-call.stderr | 7 + tests/ui/unsafe_unpin/conflict-unpin.rs | 30 + tests/ui/unsafe_unpin/conflict-unpin.stderr | 32 + tests/ui/unstable-features/README.md | 7 + .../marker_trait_attr-feature-gate.rs | 20 + .../marker_trait_attr-feature-gate.stderr | 10 + tests/ui/unstable-features/marker_trait_attr.rs | 26 + .../ui/unstable-features/marker_trait_attr.stderr | 10 + tests/ui/unstable-features/negative_impls.rs | 23 + tests/ui/unstable-features/negative_impls.stderr | 19 + .../overlapping_marker_traits-feature-gate.rs | 20 + .../overlapping_marker_traits-feature-gate.stderr | 10 + .../unstable-features/overlapping_marker_traits.rs | 30 + .../overlapping_marker_traits.stderr | 18 + .../trivial_bounds-feature-gate.rs | 53 + .../trivial_bounds-feature-gate.stderr | 59 + tests/ui/unstable-features/trivial_bounds.rs | 38 + tests/ui/unstable-features/trivial_bounds.stderr | 23 + tests/unsafe_unpin.rs | 50 + 207 files changed, 14278 insertions(+) create mode 100644 .cargo_vcs_info.json create mode 100644 CHANGELOG.md create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 Cargo.toml.orig create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-MIT create mode 100644 README.md create mode 100644 examples/README.md create mode 100644 examples/enum-default-expanded.rs create mode 100644 examples/enum-default.rs create mode 100644 examples/not_unpin-expanded.rs create mode 100644 examples/not_unpin.rs create mode 100644 examples/pinned_drop-expanded.rs create mode 100644 examples/pinned_drop.rs create mode 100644 examples/project_replace-expanded.rs create mode 100644 examples/project_replace.rs create mode 100644 examples/struct-default-expanded.rs create mode 100644 examples/struct-default.rs create mode 100644 examples/unsafe_unpin-expanded.rs create mode 100644 examples/unsafe_unpin.rs create mode 100644 src/lib.rs create mode 100644 tests/README.md create mode 100644 tests/auxiliary/mod.rs create mode 100644 tests/cfg.rs create mode 100644 tests/compiletest.rs create mode 100644 tests/drop_order.rs create mode 100644 tests/expand/default/enum.expanded.rs create mode 100644 tests/expand/default/enum.rs create mode 100644 tests/expand/default/struct.expanded.rs create mode 100644 tests/expand/default/struct.rs create mode 100644 tests/expand/default/tuple_struct.expanded.rs create mode 100644 tests/expand/default/tuple_struct.rs create mode 100644 tests/expand/multifields/enum.expanded.rs create mode 100644 tests/expand/multifields/enum.rs create mode 100644 tests/expand/multifields/struct.expanded.rs create mode 100644 tests/expand/multifields/struct.rs create mode 100644 tests/expand/multifields/tuple_struct.expanded.rs create mode 100644 tests/expand/multifields/tuple_struct.rs create mode 100644 tests/expand/naming/enum-all.expanded.rs create mode 100644 tests/expand/naming/enum-all.rs create mode 100644 tests/expand/naming/enum-mut.expanded.rs create mode 100644 tests/expand/naming/enum-mut.rs create mode 100644 tests/expand/naming/enum-none.expanded.rs create mode 100644 tests/expand/naming/enum-none.rs create mode 100644 tests/expand/naming/enum-own.expanded.rs create mode 100644 tests/expand/naming/enum-own.rs create mode 100644 tests/expand/naming/enum-ref.expanded.rs create mode 100644 tests/expand/naming/enum-ref.rs create mode 100644 tests/expand/naming/struct-all.expanded.rs create mode 100644 tests/expand/naming/struct-all.rs create mode 100644 tests/expand/naming/struct-mut.expanded.rs create mode 100644 tests/expand/naming/struct-mut.rs create mode 100644 tests/expand/naming/struct-none.expanded.rs create mode 100644 tests/expand/naming/struct-none.rs create mode 100644 tests/expand/naming/struct-own.expanded.rs create mode 100644 tests/expand/naming/struct-own.rs create mode 100644 tests/expand/naming/struct-ref.expanded.rs create mode 100644 tests/expand/naming/struct-ref.rs create mode 100644 tests/expand/naming/tuple_struct-all.expanded.rs create mode 100644 tests/expand/naming/tuple_struct-all.rs create mode 100644 tests/expand/naming/tuple_struct-mut.expanded.rs create mode 100644 tests/expand/naming/tuple_struct-mut.rs create mode 100644 tests/expand/naming/tuple_struct-none.expanded.rs create mode 100644 tests/expand/naming/tuple_struct-none.rs create mode 100644 tests/expand/naming/tuple_struct-own.expanded.rs create mode 100644 tests/expand/naming/tuple_struct-own.rs create mode 100644 tests/expand/naming/tuple_struct-ref.expanded.rs create mode 100644 tests/expand/naming/tuple_struct-ref.rs create mode 100644 tests/expand/not_unpin/enum.expanded.rs create mode 100644 tests/expand/not_unpin/enum.rs create mode 100644 tests/expand/not_unpin/struct.expanded.rs create mode 100644 tests/expand/not_unpin/struct.rs create mode 100644 tests/expand/not_unpin/tuple_struct.expanded.rs create mode 100644 tests/expand/not_unpin/tuple_struct.rs create mode 100644 tests/expand/pinned_drop/enum.expanded.rs create mode 100644 tests/expand/pinned_drop/enum.rs create mode 100644 tests/expand/pinned_drop/struct.expanded.rs create mode 100644 tests/expand/pinned_drop/struct.rs create mode 100644 tests/expand/pinned_drop/tuple_struct.expanded.rs create mode 100644 tests/expand/pinned_drop/tuple_struct.rs create mode 100644 tests/expand/project_replace/enum.expanded.rs create mode 100644 tests/expand/project_replace/enum.rs create mode 100644 tests/expand/project_replace/struct.expanded.rs create mode 100644 tests/expand/project_replace/struct.rs create mode 100644 tests/expand/project_replace/tuple_struct.expanded.rs create mode 100644 tests/expand/project_replace/tuple_struct.rs create mode 100644 tests/expand/pub/enum.expanded.rs create mode 100644 tests/expand/pub/enum.rs create mode 100644 tests/expand/pub/struct.expanded.rs create mode 100644 tests/expand/pub/struct.rs create mode 100644 tests/expand/pub/tuple_struct.expanded.rs create mode 100644 tests/expand/pub/tuple_struct.rs create mode 100644 tests/expand/unsafe_unpin/enum.expanded.rs create mode 100644 tests/expand/unsafe_unpin/enum.rs create mode 100644 tests/expand/unsafe_unpin/struct.expanded.rs create mode 100644 tests/expand/unsafe_unpin/struct.rs create mode 100644 tests/expand/unsafe_unpin/tuple_struct.expanded.rs create mode 100644 tests/expand/unsafe_unpin/tuple_struct.rs create mode 100644 tests/expandtest.rs create mode 100644 tests/include/basic-safe-part.rs create mode 100644 tests/include/basic.rs create mode 100644 tests/lint.rs create mode 100644 tests/pin_project.rs create mode 100644 tests/pinned_drop.rs create mode 100644 tests/proper_unpin.rs create mode 100644 tests/repr_packed.rs create mode 100644 tests/ui/cfg/cfg_attr-resolve.rs create mode 100644 tests/ui/cfg/cfg_attr-resolve.stderr create mode 100644 tests/ui/cfg/cfg_attr-type-mismatch.rs create mode 100644 tests/ui/cfg/cfg_attr-type-mismatch.stderr create mode 100644 tests/ui/cfg/packed_sneaky-span-issue-1.rs create mode 100644 tests/ui/cfg/packed_sneaky-span-issue-1.stderr create mode 100644 tests/ui/cfg/packed_sneaky-span-issue-2.rs create mode 100644 tests/ui/cfg/packed_sneaky-span-issue-2.stderr create mode 100644 tests/ui/cfg/packed_sneaky.rs create mode 100644 tests/ui/cfg/packed_sneaky.stderr create mode 100644 tests/ui/cfg/unsupported.rs create mode 100644 tests/ui/cfg/unsupported.stderr create mode 100644 tests/ui/not_unpin/conflict-unpin.rs create mode 100644 tests/ui/not_unpin/conflict-unpin.stderr create mode 100644 tests/ui/not_unpin/impl-unsafe-unpin.rs create mode 100644 tests/ui/not_unpin/impl-unsafe-unpin.stderr create mode 100644 tests/ui/pin_project/add-attr-to-struct.rs create mode 100644 tests/ui/pin_project/add-attr-to-struct.stderr create mode 100644 tests/ui/pin_project/add-pinned-field.rs create mode 100644 tests/ui/pin_project/add-pinned-field.stderr create mode 100644 tests/ui/pin_project/conflict-drop.rs create mode 100644 tests/ui/pin_project/conflict-drop.stderr create mode 100644 tests/ui/pin_project/conflict-unpin.rs create mode 100644 tests/ui/pin_project/conflict-unpin.stderr create mode 100644 tests/ui/pin_project/impl-unsafe-unpin.rs create mode 100644 tests/ui/pin_project/impl-unsafe-unpin.stderr create mode 100644 tests/ui/pin_project/import_unnamed.rs create mode 100644 tests/ui/pin_project/import_unnamed.stderr create mode 100644 tests/ui/pin_project/invalid.rs create mode 100644 tests/ui/pin_project/invalid.stderr create mode 100644 tests/ui/pin_project/overlapping_unpin_struct.rs create mode 100644 tests/ui/pin_project/overlapping_unpin_struct.stderr create mode 100644 tests/ui/pin_project/override-priv-mod.rs create mode 100644 tests/ui/pin_project/override-priv-mod.stderr create mode 100644 tests/ui/pin_project/packed-enum.rs create mode 100644 tests/ui/pin_project/packed-enum.stderr create mode 100644 tests/ui/pin_project/packed-name-value.rs create mode 100644 tests/ui/pin_project/packed-name-value.stderr create mode 100644 tests/ui/pin_project/packed.rs create mode 100644 tests/ui/pin_project/packed.stderr create mode 100644 tests/ui/pin_project/packed_sneaky-1.rs create mode 100644 tests/ui/pin_project/packed_sneaky-1.stderr create mode 100644 tests/ui/pin_project/packed_sneaky-2.rs create mode 100644 tests/ui/pin_project/packed_sneaky-2.stderr create mode 100644 tests/ui/pin_project/packed_sneaky-3.rs create mode 100644 tests/ui/pin_project/packed_sneaky-3.stderr create mode 100644 tests/ui/pin_project/packed_sneaky-4.rs create mode 100644 tests/ui/pin_project/packed_sneaky-4.stderr create mode 100644 tests/ui/pin_project/private_in_public-enum.rs create mode 100644 tests/ui/pin_project/private_in_public-enum.stderr create mode 100644 tests/ui/pin_project/project_replace_unsized.rs create mode 100644 tests/ui/pin_project/project_replace_unsized.stderr create mode 100644 tests/ui/pin_project/project_replace_unsized_fn_params.rs create mode 100644 tests/ui/pin_project/project_replace_unsized_fn_params.stderr create mode 100644 tests/ui/pin_project/remove-attr-from-field.rs create mode 100644 tests/ui/pin_project/remove-attr-from-field.stderr create mode 100644 tests/ui/pin_project/remove-attr-from-struct.rs create mode 100644 tests/ui/pin_project/remove-attr-from-struct.stderr create mode 100644 tests/ui/pin_project/safe_packed_borrows.rs create mode 100644 tests/ui/pin_project/safe_packed_borrows.stderr create mode 100644 tests/ui/pin_project/unaligned_references.rs create mode 100644 tests/ui/pin_project/unaligned_references.stderr create mode 100644 tests/ui/pin_project/unpin_sneaky.rs create mode 100644 tests/ui/pin_project/unpin_sneaky.stderr create mode 100644 tests/ui/pin_project/visibility.rs create mode 100644 tests/ui/pin_project/visibility.stderr create mode 100644 tests/ui/pinned_drop/call-drop-inner.rs create mode 100644 tests/ui/pinned_drop/call-drop-inner.stderr create mode 100644 tests/ui/pinned_drop/conditional-drop-impl.rs create mode 100644 tests/ui/pinned_drop/conditional-drop-impl.stderr create mode 100644 tests/ui/pinned_drop/forget-pinned-drop-impl.rs create mode 100644 tests/ui/pinned_drop/forget-pinned-drop-impl.stderr create mode 100644 tests/ui/pinned_drop/invalid-self.rs create mode 100644 tests/ui/pinned_drop/invalid-self.stderr create mode 100644 tests/ui/pinned_drop/invalid.rs create mode 100644 tests/ui/pinned_drop/invalid.stderr create mode 100644 tests/ui/pinned_drop/pinned-drop-no-attr-arg.rs create mode 100644 tests/ui/pinned_drop/pinned-drop-no-attr-arg.stderr create mode 100644 tests/ui/pinned_drop/self.rs create mode 100644 tests/ui/pinned_drop/self.stderr create mode 100644 tests/ui/pinned_drop/unsafe-call.rs create mode 100644 tests/ui/pinned_drop/unsafe-call.stderr create mode 100644 tests/ui/unsafe_unpin/conflict-unpin.rs create mode 100644 tests/ui/unsafe_unpin/conflict-unpin.stderr create mode 100644 tests/ui/unstable-features/README.md create mode 100644 tests/ui/unstable-features/marker_trait_attr-feature-gate.rs create mode 100644 tests/ui/unstable-features/marker_trait_attr-feature-gate.stderr create mode 100644 tests/ui/unstable-features/marker_trait_attr.rs create mode 100644 tests/ui/unstable-features/marker_trait_attr.stderr create mode 100644 tests/ui/unstable-features/negative_impls.rs create mode 100644 tests/ui/unstable-features/negative_impls.stderr create mode 100644 tests/ui/unstable-features/overlapping_marker_traits-feature-gate.rs create mode 100644 tests/ui/unstable-features/overlapping_marker_traits-feature-gate.stderr create mode 100644 tests/ui/unstable-features/overlapping_marker_traits.rs create mode 100644 tests/ui/unstable-features/overlapping_marker_traits.stderr create mode 100644 tests/ui/unstable-features/trivial_bounds-feature-gate.rs create mode 100644 tests/ui/unstable-features/trivial_bounds-feature-gate.stderr create mode 100644 tests/ui/unstable-features/trivial_bounds.rs create mode 100644 tests/ui/unstable-features/trivial_bounds.stderr create mode 100644 tests/unsafe_unpin.rs diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json new file mode 100644 index 0000000..401be20 --- /dev/null +++ b/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "d1c11dc50f88330cfb05ac55aaa06c28877eb1d6" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..76e245f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,758 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +This project adheres to [Semantic Versioning](https://semver.org). + + + +## [Unreleased] + +## [1.0.12] - 2022-08-15 + +- Suppress `unused_tuple_struct_fields` lint in generated code. + +## [1.0.11] - 2022-07-02 + +- [Suppress `dead_code` lint in generated code.](https://github.com/taiki-e/pin-project/pull/346) + +## [1.0.10] - 2021-12-31 + +- Revert the increase of the minimal version of `syn` that was done in 1.0.9. + +## [1.0.9] - 2021-12-26 + +- [Prevent abuse of private module.](https://github.com/taiki-e/pin-project/pull/336) + +- Update minimal version of `syn` to 1.0.84. + +## [1.0.8] - 2021-07-21 + +- [Suppress `clippy::use_self` and `clippy::type_repetition_in_bounds` lints in generated code.](https://github.com/taiki-e/pin-project/pull/331) + +## [1.0.7] - 2021-04-16 + +- [Fix compile error when using `self::` as prefix of path inside `#[pinned_drop]` impl.](https://github.com/taiki-e/pin-project/pull/326) + +## [1.0.6] - 2021-03-25 + +- [Suppress `clippy::semicolon_if_nothing_returned` lint in generated code.](https://github.com/taiki-e/pin-project/pull/318) + +## [1.0.5] - 2021-02-03 + +- [Suppress `deprecated` lint in generated code.](https://github.com/taiki-e/pin-project/pull/313) + +## [1.0.4] - 2021-01-09 + +- [Suppress `clippy::ref_option_ref` lint in generated code.](https://github.com/taiki-e/pin-project/pull/308) + +## [1.0.3] - 2021-01-05 + +- Exclude unneeded files from crates.io. + +## [1.0.2] - 2020-11-18 + +- [Suppress `clippy::unknown_clippy_lints` lint in generated code.](https://github.com/taiki-e/pin-project/pull/303) + +## [1.0.1] - 2020-10-15 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/commit/ddcd88079ba2d82857c365f2a3543ad146ade54c). + +- [Fix warnings when `#[pin_project]` attribute used within `macro_rules!` macros.](https://github.com/taiki-e/pin-project/pull/298) + +## [1.0.0] - 2020-10-13 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/commit/ddcd88079ba2d82857c365f2a3543ad146ade54c). + +- [Remove deprecated `#[project]`, `#[project_ref]`, and `#[project_replace]` attributes.](https://github.com/taiki-e/pin-project/pull/265) + + Name the projected type by passing an argument with the same name as the method to the `#[pin_project]` attribute instead: + + ```diff + - #[pin_project] + + #[pin_project(project = EnumProj)] + enum Enum { + Variant(#[pin] T), + } + + - #[project] + fn func(x: Pin<&mut Enum>) { + - #[project] + match x.project() { + - Enum::Variant(_) => { /* ... */ } + + EnumProj::Variant(_) => { /* ... */ } + } + } + ``` + +- [Remove deprecated `Replace` argument from `#[pin_project]` attribute.](https://github.com/taiki-e/pin-project/pull/266) Use `project_replace` argument instead. + +- [Optimize code generation when used on enums.](https://github.com/taiki-e/pin-project/pull/270) + +- [Raise the minimum supported Rust version of this crate from Rust 1.34 to Rust 1.37.](https://github.com/taiki-e/pin-project/pull/292) + +- Suppress `explicit_outlives_requirements`, `box_pointers`, `clippy::large_enum_variant`, `clippy::pattern_type_mismatch`, `clippy::implicit_return`, and `clippy::redundant_pub_crate` lints in generated code. ([#276](https://github.com/taiki-e/pin-project/pull/276), [#277](https://github.com/taiki-e/pin-project/pull/277), [#284](https://github.com/taiki-e/pin-project/pull/284)) + +- Diagnostic improvements. + +Changes since the 1.0.0-alpha.1 release: + +- [Fix drop order of pinned fields in `project_replace`.](https://github.com/taiki-e/pin-project/pull/287) + +- Update minimal version of `syn` to 1.0.44. + +## [1.0.0-alpha.1] - 2020-09-22 + +- [Remove deprecated `#[project]`, `#[project_ref]`, and `#[project_replace]` attributes.](https://github.com/taiki-e/pin-project/pull/265) + + Name the projected type by passing an argument with the same name as the method to the `#[pin_project]` attribute instead: + + ```diff + - #[pin_project] + + #[pin_project(project = EnumProj)] + enum Enum { + Variant(#[pin] T), + } + + - #[project] + fn func(x: Pin<&mut Enum>) { + - #[project] + match x.project() { + - Enum::Variant(_) => { /* ... */ } + + EnumProj::Variant(_) => { /* ... */ } + } + } + ``` + +- [Remove deprecated `Replace` argument from `#[pin_project]` attribute.](https://github.com/taiki-e/pin-project/pull/266) Use `project_replace` argument instead. + +- [Optimize code generation when used on enums.](https://github.com/taiki-e/pin-project/pull/270) + +- Suppress `explicit_outlives_requirements`, `box_pointers`, `clippy::large_enum_variant`, `clippy::pattern_type_mismatch`, and `clippy::implicit_return` lints in generated code. ([#276](https://github.com/taiki-e/pin-project/pull/276), [#277](https://github.com/taiki-e/pin-project/pull/277)) + +- Diagnostic improvements. + +See also [tracking issue for 1.0 release](https://github.com/taiki-e/pin-project/issues/264). + +## [0.4.30] - 2022-07-02 + +- [Suppress `dead_code` lint in generated code.](https://github.com/taiki-e/pin-project/pull/347) + +## [0.4.29] - 2021-12-26 + +- [Fix compile error with `syn` 1.0.84 and later.](https://github.com/taiki-e/pin-project/pull/335) + +## [0.4.28] - 2021-03-28 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Fix `unused_must_use` warning on unused borrows, which will be added to rustc in the future.](https://github.com/taiki-e/pin-project/pull/322) See [#322](https://github.com/taiki-e/pin-project/pull/322) for more details. + + (Note: 1.0 does not have this problem.) + +## [0.4.27] - 2020-10-11 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- Update minimal version of `syn` to 1.0.44. + +## [0.4.26] - 2020-10-04 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Fix drop order of pinned fields in `project_replace`.](https://github.com/taiki-e/pin-project/pull/287) + +## [0.4.25] - 2020-10-01 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Suppress `drop_bounds` lint, which will be added to rustc in the future.](https://github.com/taiki-e/pin-project/pull/273) See [#272](https://github.com/taiki-e/pin-project/issues/272) for more details. + + (Note: 1.0.0-alpha.1 already contains this change.) + +## [0.4.24] - 2020-09-26 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Fix compatibility of generated code with `forbid(future_incompatible)`.](https://github.com/taiki-e/pin-project/pull/282) + + Note: This does not guarantee compatibility with `forbid(future_incompatible)` in the future. + If rustc adds a new lint, we may not be able to keep this. + +## [0.4.23] - 2020-07-27 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Fix compile error with `?Sized` type parameters.](https://github.com/taiki-e/pin-project/pull/263) + +## [0.4.22] - 2020-06-14 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- Documentation improvements. + +## [0.4.21] - 2020-06-13 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Deprecated `#[project]`, `#[project_ref]`, and `#[project_replace]` attributes due to some unfixable limitations.](https://github.com/taiki-e/pin-project/pull/244) + + Consider naming the projected type by passing an argument with the same name as the method to the `#[pin_project]` attribute instead. + + ```rust + #[pin_project(project = EnumProj)] + enum Enum { + Variant(#[pin] T), + } + + fn func(x: Pin<&mut Enum>) { + match x.project() { + EnumProj::Variant(y) => { + let _: Pin<&mut T> = y; + } + } + } + ``` + + See [#225](https://github.com/taiki-e/pin-project/pull/225) for more details. + +- [Support `Self` in fields and generics in type definitions.](https://github.com/taiki-e/pin-project/pull/245) + +- [Fix errors involving *"`self` value is a keyword only available in methods with `self` parameter"* in apparently correct code.](https://github.com/taiki-e/pin-project/pull/250) + +- Diagnostic improvements. + +## [0.4.20] - 2020-06-07 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [You can now use `project_replace` argument without Replace argument.](https://github.com/taiki-e/pin-project/pull/243) + This used to require you to specify both. + + ```diff + - #[pin_project(Replace, project_replace = EnumProjOwn)] + + #[pin_project(project_replace = EnumProjOwn)] + enum Enum { + Variant(#[pin] T) + } + ``` + +- [Make `project_replace` argument an alias for `Replace` argument so that it can be used without a value.](https://github.com/taiki-e/pin-project/pull/243) + + ```rust + #[pin_project(project_replace)] + enum Enum { + Variant(#[pin] T) + } + ``` + + *The `Replace` argument will be deprecated in the future.* + +- [Suppress `unreachable_pub` lint in generated code.](https://github.com/taiki-e/pin-project/pull/240) + +## [0.4.19] - 2020-06-04 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Suppress `unused_results` lint in generated code.](https://github.com/taiki-e/pin-project/pull/239) + +## [0.4.18] - 2020-06-04 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Support `Self` in more syntax positions inside `#[pinned_drop]` impl.](https://github.com/taiki-e/pin-project/pull/230) + +- [Suppress `clippy::type_repetition_in_bounds` and `clippy::used_underscore_binding` lints in generated code.](https://github.com/taiki-e/pin-project/pull/233) + +- Documentation improvements. + +- Diagnostic improvements. + +## [0.4.17] - 2020-05-18 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Support naming the projection types.](https://github.com/taiki-e/pin-project/pull/202) + + By passing an argument with the same name as the method to the attribute, you can name the projection type returned from the method: + + ```rust + #[pin_project(project = EnumProj)] + enum Enum { + Variant(#[pin] T), + } + + fn func(x: Pin<&mut Enum>) { + match x.project() { + EnumProj::Variant(y) => { + let _: Pin<&mut T> = y; + } + } + } + ``` + +## [0.4.16] - 2020-05-11 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Fix an issue that users can call internal function generated by `#[pinned_drop]`.](https://github.com/taiki-e/pin-project/pull/223) + +## [0.4.15] - 2020-05-10 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [`#[project]` attribute can now handle all `project*` attributes in that scope with one wrapper attribute.](https://github.com/taiki-e/pin-project/pull/220) + +## [0.4.14] - 2020-05-09 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Add `!Unpin` option to `#[pin_project]` attribute for guarantee the type is `!Unpin`.](https://github.com/taiki-e/pin-project/pull/219) + + ```rust + #[pin_project(!Unpin)] + struct Struct { + field: T, + } + ``` + + This is equivalent to use `#[pin]` attribute for `PhantomPinned` field. + + ```rust + #[pin_project] + struct Struct { + field: T, + #[pin] // Note that using `PhantomPinned` without `#[pin]` attribute has no effect. + _pin: PhantomPinned, + } + ``` + + *[Note: This raises the minimum supported Rust version of this crate from Rust 1.33 to Rust 1.34.](https://github.com/taiki-e/pin-project/pull/219#pullrequestreview-408644187)* + +- [Fix an issue where duplicate `#[project]` attributes were ignored.](https://github.com/taiki-e/pin-project/pull/218) + +- [Suppress `single_use_lifetimes` lint in generated code.](https://github.com/taiki-e/pin-project/pull/217) + +- [Support overlapping lifetime names in HRTB.](https://github.com/taiki-e/pin-project/pull/217) + +- [Hide generated items from --document-private-items.](https://github.com/taiki-e/pin-project/pull/211) See [#211](https://github.com/taiki-e/pin-project/pull/211) for details. + +- Documentation improvements. + +## [0.4.13] - 2020-05-07 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Fix a regression in 0.4.11.](https://github.com/taiki-e/pin-project/pull/207) + + Changes from [0.4.10](https://github.com/taiki-e/pin-project/releases/tag/v0.4.10) and [0.4.12](https://github.com/taiki-e/pin-project/releases/tag/v0.4.12): + + - [Fix an issue that `#[project]` on non-statement expression does not work without unstable features.](https://github.com/taiki-e/pin-project/pull/197) + + - [Support overwriting the name of core crate.](https://github.com/taiki-e/pin-project/pull/199) + + - [Suppress `clippy::needless_pass_by_value` lint in generated code of `#[pinned_drop]`.](https://github.com/taiki-e/pin-project/pull/200) + + - Documentation improvements. + + - Diagnostic improvements. + +## [0.4.12] - 2020-05-07 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- A release to avoid [a regression in 0.4.11](https://github.com/taiki-e/pin-project/issues/206). No code changes from [0.4.10](https://github.com/taiki-e/pin-project/releases/tag/v0.4.10). + +## [0.4.11] - 2020-05-07 + +**Note:** This release has been yanked. See [#206](https://github.com/taiki-e/pin-project/issues/206) for details. + +- [Fix an issue that `#[project]` on non-statement expression does not work without unstable features.](https://github.com/taiki-e/pin-project/pull/197) + +- [Support overwriting the name of core crate.](https://github.com/taiki-e/pin-project/pull/199) + +- [Suppress `clippy::needless_pass_by_value` lint in generated code of `#[pinned_drop]`.](https://github.com/taiki-e/pin-project/pull/200) + +- Documentation improvements. + +- Diagnostic improvements. + +## [0.4.10] - 2020-05-04 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Add `project_replace` method and `#[project_replace]` attribute.](https://github.com/taiki-e/pin-project/pull/194) + `project_replace` method is optional and can be enabled by passing the `Replace` argument to `#[pin_project]` attribute. + See [the documentation](https://docs.rs/pin-project/0.4/pin_project/attr.pin_project.html#project_replace) for more details. + +- [Support `Self` and `self` in more syntax positions inside `#[pinned_drop]` impl.](https://github.com/taiki-e/pin-project/pull/190) + +- [Hide all generated items except for projected types from calling code.](https://github.com/taiki-e/pin-project/pull/192) See [#192](https://github.com/taiki-e/pin-project/pull/192) for details. + +## [0.4.9] - 2020-04-14 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Fix lifetime inference error when associated types are used in fields.](https://github.com/taiki-e/pin-project/pull/188) + +- [Fix compile error with tuple structs with `where` clauses.](https://github.com/taiki-e/pin-project/pull/186) + +- [`#[project]` attribute can now be used for `if let` expressions.](https://github.com/taiki-e/pin-project/pull/181) + +## [0.4.8] - 2020-01-27 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Ensure that users cannot implement `PinnedDrop` without proper attribute argument.](https://github.com/taiki-e/pin-project/pull/180) + +- [Fix use of `Self` in expression position inside `#[pinned_drop]` impl.](https://github.com/taiki-e/pin-project/pull/177) + +## [0.4.7] - 2020-01-20 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Fix support for lifetime bounds.](https://github.com/taiki-e/pin-project/pull/176) + +## [0.4.6] - 2019-11-20 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Fix compile error when there is `Self` in the where clause.](https://github.com/taiki-e/pin-project/pull/169) + +## [0.4.5] - 2019-10-21 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Fix compile error with `dyn` types.](https://github.com/taiki-e/pin-project/pull/158) + +## [0.4.4] - 2019-10-17 + +**Note:** This release has been yanked because it [failed to compile with syn 1.0.84 and later](https://github.com/taiki-e/pin-project/pull/335). + +- [Fix an issue where `PinnedDrop` implementations can call unsafe code without an unsafe block.](https://github.com/taiki-e/pin-project/pull/149) + +## [0.4.3] - 2019-10-15 + +**Note:** This release has been yanked. See [#148](https://github.com/taiki-e/pin-project/pull/148) for details. + +- [`#[pin_project]` can now interoperate with `#[cfg_attr()]`.](https://github.com/taiki-e/pin-project/pull/135) + +- [`#[pin_project]` can now interoperate with `#[cfg()]` on tuple structs and tuple variants.](https://github.com/taiki-e/pin-project/pull/135) + +- [Fix support for DSTs(Dynamically Sized Types) on `#[pin_project(UnsafeUnpin)]`](https://github.com/taiki-e/pin-project/pull/120) + +- Diagnostic improvements. + +## [0.4.2] - 2019-09-29 + +**Note:** This release has been yanked. See [#148](https://github.com/taiki-e/pin-project/pull/148) for details. + +- [Fix support for DSTs(Dynamically Sized Types).](https://github.com/taiki-e/pin-project/pull/113) + +## [0.4.1] - 2019-09-26 + +**Note:** This release has been yanked. See [#148](https://github.com/taiki-e/pin-project/pull/148) for details. + +- [Fix an issue that caused an error when using `#[pin_project]` on a type that has `#[pin]` + `!Unpin` field with no generics or lifetime.](https://github.com/taiki-e/pin-project/pull/111) + +## [0.4.0] - 2019-09-25 + +**Note:** This release has been yanked. See [#148](https://github.com/taiki-e/pin-project/pull/148) for details. + +- [**Pin projection has become a safe operation.**](https://github.com/taiki-e/pin-project/pull/18) In the absence of other unsafe code that you write, it is impossible to cause undefined behavior. + +- `#[unsafe_project]` attribute has been replaced with `#[pin_project]` attribute. ([#18](https://github.com/taiki-e/pin-project/pull/18), [#33](https://github.com/taiki-e/pin-project/pull/33)) + +- [The `Unpin` argument has been removed - an `Unpin` impl is now generated by default.](https://github.com/taiki-e/pin-project/pull/18) + +- Drop impls must be specified with `#[pinned_drop]` instead of via a normal `Drop` impl. ([#18](https://github.com/taiki-e/pin-project/pull/18), [#33](https://github.com/taiki-e/pin-project/pull/33), [#86](https://github.com/taiki-e/pin-project/pull/86)) + +- [`Unpin` impls must be specified with an impl of `UnsafeUnpin`, instead of implementing the normal `Unpin` trait.](https://github.com/taiki-e/pin-project/pull/18) + +- [`#[pin_project]` attribute now determines the visibility of the projection type/method is based on the original type.](https://github.com/taiki-e/pin-project/pull/96) + +- [`#[pin_project]` can now be used for public type with private field types.](https://github.com/taiki-e/pin-project/pull/53) + +- [`#[pin_project]` can now interoperate with `#[cfg()]`.](https://github.com/taiki-e/pin-project/pull/77) + +- [Add `project_ref` method to `#[pin_project]` types.](https://github.com/taiki-e/pin-project/pull/93) + +- [Add `#[project_ref]` attribute.](https://github.com/taiki-e/pin-project/pull/93) + +- [Remove "project_attr" feature and always enable `#[project]` attribute.](https://github.com/taiki-e/pin-project/pull/94) + +- [`#[project]` attribute can now be used for `impl` blocks.](https://github.com/taiki-e/pin-project/pull/46) + +- [`#[project]` attribute can now be used for `use` statements.](https://github.com/taiki-e/pin-project/pull/85) + +- [`#[project]` attribute now supports `match` expressions at the position of the initializer expression of `let` expressions.](https://github.com/taiki-e/pin-project/pull/51) + +Changes since the 0.4.0-beta.1 release: + +- [Fix an issue that caused an error when using `#[pin_project(UnsafeUnpin)]` and not providing a manual `UnsafeUnpin` implementation on a type with no generics or lifetime.](https://github.com/taiki-e/pin-project/pull/107) + +## [0.4.0-beta.1] - 2019-09-21 + +- [Change the argument type of project method back to `self: Pin<&mut Self>`.](https://github.com/taiki-e/pin-project/pull/90) + +- [Remove "project_attr" feature and always enable `#[project]` attribute.](https://github.com/taiki-e/pin-project/pull/94) + +- [Remove "renamed" feature.](https://github.com/taiki-e/pin-project/pull/100) + +- [`#[project]` attribute can now be used for `use` statements.](https://github.com/taiki-e/pin-project/pull/85) + +- [Add `project_ref` method and `#[project_ref]` attribute.](https://github.com/taiki-e/pin-project/pull/93) + +- [`#[pin_project]` attribute now determines the visibility of the projection type/method is based on the original type.](https://github.com/taiki-e/pin-project/pull/96) + +## [0.4.0-alpha.11] - 2019-09-11 + +- [Change #[pinned_drop] to trait implementation.](https://github.com/taiki-e/pin-project/pull/86) + + ```rust + #[pinned_drop] + impl PinnedDrop for Foo<'_, T> { + fn drop(mut self: Pin<&mut Self>) { + **self.project().was_dropped = true; + } + } + ``` + +- Add some examples and generated code. + +- Diagnostic improvements. + +## [0.4.0-alpha.10] - 2019-09-07 + +- [`#[pin_project]` can now interoperate with `#[cfg()]`.](https://github.com/taiki-e/pin-project/pull/77) + +- Documentation improvements. + +## [0.4.0-alpha.9] - 2019-09-05 + +- [Add `project_into` method to `#[pin_project]` types](https://github.com/taiki-e/pin-project/pull/69). This can be useful when returning a pin projection from a method. + + ```rust + fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { + self.project_into().pinned + } + ``` + +- [Prevent `UnpinStruct` from appearing in the document by default.](https://github.com/taiki-e/pin-project/pull/71) See [#71](https://github.com/taiki-e/pin-project/pull/71) for more details. + +## [0.4.0-alpha.8] - 2019-09-03 + +- [Improve document of generated code.](https://github.com/taiki-e/pin-project/pull/62). Also added an option to control the document of generated code. See [#62](https://github.com/taiki-e/pin-project/pull/62) for more details. + +- [Diagnostic improvements.](https://github.com/taiki-e/pin-project/pull/61) + +## [0.4.0-alpha.7] - 2019-09-02 + +- [Suppress `dead_code` lint in generated types.](https://github.com/taiki-e/pin-project/pull/57) + +## [0.4.0-alpha.6] - 2019-09-01 + +- [Allow using `#[pin_project]` type with private field types](https://github.com/taiki-e/pin-project/pull/53) + +## [0.4.0-alpha.5] - 2019-08-24 + +- [`#[project]` attribute now supports `match` expressions at the position of the initializer expression of `let` expressions.](https://github.com/taiki-e/pin-project/pull/51) + +## [0.4.0-alpha.4] - 2019-08-23 + +- Suppress `clippy::drop_bounds` lint in generated code. + +## [0.4.0-alpha.3] - 2019-08-23 + +- [Change `project` method generated by `#[pin_project]` attribute to take an `&mut Pin<&mut Self>` argument.](https://github.com/taiki-e/pin-project/pull/47) + +- [`#[project]` attribute can now be used for impl blocks.](https://github.com/taiki-e/pin-project/pull/46) + +- [`#[pin_project]` attribute can now detect that the type used does not have its own drop implementation without actually implementing drop.](https://github.com/taiki-e/pin-project/pull/48) This removed some restrictions. + +## [0.4.0-alpha.2] - 2019-08-13 + +- Update `proc-macro2`, `syn`, and `quote` to 1.0. + +## [0.4.0-alpha.1] - 2019-08-11 + +- **Pin projection has become a safe operation.** + +- `#[unsafe_project]` has been replaced with `#[pin_project]`. + +- The `Unpin` argument has been removed - an `Unpin` impl is now generated by default. + +- Drop impls must be specified with `#[pinned_drop]` instead of via a normal `Drop` impl. + +- `Unpin` impls must be specified with an impl of `UnsafeUnpin`, instead of implementing the normal `Unpin` trait. + +- Make `#[project]` attribute disabled by default. + +See also [tracking issue for 0.4 release](https://github.com/taiki-e/pin-project/issues/21). + +## [0.3.5] - 2019-08-14 + +- Update `proc-macro2`, `syn`, and `quote` to 1.0. + +## [0.3.4] - 2019-07-21 + +- Diagnostic improvements. + +## [0.3.3] - 2019-07-15 + +**Note:** This release has been yanked. See [#16](https://github.com/taiki-e/pin-project/issues/16) for details. + +- Diagnostic improvements. + +## [0.3.2] - 2019-03-30 + +- Avoid suffixes on tuple index. + +## [0.3.1] - 2019-03-02 + +- Documentation improvements. + +- Update minimum `syn` version to 0.15.22. + +## [0.3.0] - 2019-02-20 + +- Remove `unsafe_fields` attribute. + +- Remove `unsafe_variants` attribute. + +## [0.2.2] - 2019-02-20 + +- Fix a bug that generates incorrect code for the some structures with trait bounds on type generics. + +## [0.2.1] - 2019-02-20 + +- Fix a bug that generates incorrect code for the structures with where clause and associated type fields. + +## [0.2.0] - 2019-02-11 + +- Make `unsafe_fields` optional. + +- Documentation improvements. + +## [0.1.8] - 2019-02-02 + +- Add the feature to create projected enums to `unsafe_project`. + +- Add `project` attribute to support pattern matching. + +## [0.1.7] - 2019-01-19 + +- Fix documentation. + +## [0.1.6] - 2019-01-19 + +- `unsafe_fields` can now opt-out. + +- Add `unsafe_variants` attribute. This attribute is available if pin-project is built with the "unsafe_variants" feature. + +## [0.1.5] - 2019-01-17 + +- Add support for tuple struct to `unsafe_project`. + +## [0.1.4] - 2019-01-12 + +- Add options for automatically implementing `Unpin` to both `unsafe_project` and `unsafe_fields`. + +## [0.1.3] - 2019-01-11 + +- Fix dependencies. + +- Add `unsafe_fields` attribute. + +## [0.1.2] - 2019-01-09 + +- Documentation improvements. + +## [0.1.1] - 2019-01-08 + +- Rename from `unsafe_pin_project` to `unsafe_project`. + +## [0.1.0] - 2019-01-08 + +**Note:** This release has been yanked. + +Initial release + +[Unreleased]: https://github.com/taiki-e/pin-project/compare/v1.0.12...HEAD +[1.0.12]: https://github.com/taiki-e/pin-project/compare/v1.0.11...v1.0.12 +[1.0.11]: https://github.com/taiki-e/pin-project/compare/v1.0.10...v1.0.11 +[1.0.10]: https://github.com/taiki-e/pin-project/compare/v1.0.9...v1.0.10 +[1.0.9]: https://github.com/taiki-e/pin-project/compare/v1.0.8...v1.0.9 +[1.0.8]: https://github.com/taiki-e/pin-project/compare/v1.0.7...v1.0.8 +[1.0.7]: https://github.com/taiki-e/pin-project/compare/v1.0.6...v1.0.7 +[1.0.6]: https://github.com/taiki-e/pin-project/compare/v1.0.5...v1.0.6 +[1.0.5]: https://github.com/taiki-e/pin-project/compare/v1.0.4...v1.0.5 +[1.0.4]: https://github.com/taiki-e/pin-project/compare/v1.0.3...v1.0.4 +[1.0.3]: https://github.com/taiki-e/pin-project/compare/v1.0.2...v1.0.3 +[1.0.2]: https://github.com/taiki-e/pin-project/compare/v1.0.1...v1.0.2 +[1.0.1]: https://github.com/taiki-e/pin-project/compare/v1.0.0...v1.0.1 +[1.0.0]: https://github.com/taiki-e/pin-project/compare/v1.0.0-alpha.1...v1.0.0 +[1.0.0-alpha.1]: https://github.com/taiki-e/pin-project/compare/v0.4.23...v1.0.0-alpha.1 +[0.4.30]: https://github.com/taiki-e/pin-project/compare/v0.4.29...v0.4.30 +[0.4.29]: https://github.com/taiki-e/pin-project/compare/v0.4.28...v0.4.29 +[0.4.28]: https://github.com/taiki-e/pin-project/compare/v0.4.27...v0.4.28 +[0.4.27]: https://github.com/taiki-e/pin-project/compare/v0.4.26...v0.4.27 +[0.4.26]: https://github.com/taiki-e/pin-project/compare/v0.4.25...v0.4.26 +[0.4.25]: https://github.com/taiki-e/pin-project/compare/v0.4.24...v0.4.25 +[0.4.24]: https://github.com/taiki-e/pin-project/compare/v0.4.23...v0.4.24 +[0.4.23]: https://github.com/taiki-e/pin-project/compare/v0.4.22...v0.4.23 +[0.4.22]: https://github.com/taiki-e/pin-project/compare/v0.4.21...v0.4.22 +[0.4.21]: https://github.com/taiki-e/pin-project/compare/v0.4.20...v0.4.21 +[0.4.20]: https://github.com/taiki-e/pin-project/compare/v0.4.19...v0.4.20 +[0.4.19]: https://github.com/taiki-e/pin-project/compare/v0.4.18...v0.4.19 +[0.4.18]: https://github.com/taiki-e/pin-project/compare/v0.4.17...v0.4.18 +[0.4.17]: https://github.com/taiki-e/pin-project/compare/v0.4.16...v0.4.17 +[0.4.16]: https://github.com/taiki-e/pin-project/compare/v0.4.15...v0.4.16 +[0.4.15]: https://github.com/taiki-e/pin-project/compare/v0.4.14...v0.4.15 +[0.4.14]: https://github.com/taiki-e/pin-project/compare/v0.4.13...v0.4.14 +[0.4.13]: https://github.com/taiki-e/pin-project/compare/v0.4.11...v0.4.13 +[0.4.12]: https://github.com/taiki-e/pin-project/compare/v0.4.10...v0.4.12 +[0.4.11]: https://github.com/taiki-e/pin-project/compare/v0.4.10...v0.4.11 +[0.4.10]: https://github.com/taiki-e/pin-project/compare/v0.4.9...v0.4.10 +[0.4.9]: https://github.com/taiki-e/pin-project/compare/v0.4.8...v0.4.9 +[0.4.8]: https://github.com/taiki-e/pin-project/compare/v0.4.7...v0.4.8 +[0.4.7]: https://github.com/taiki-e/pin-project/compare/v0.4.6...v0.4.7 +[0.4.6]: https://github.com/taiki-e/pin-project/compare/v0.4.5...v0.4.6 +[0.4.5]: https://github.com/taiki-e/pin-project/compare/v0.4.4...v0.4.5 +[0.4.4]: https://github.com/taiki-e/pin-project/compare/v0.4.3...v0.4.4 +[0.4.3]: https://github.com/taiki-e/pin-project/compare/v0.4.2...v0.4.3 +[0.4.2]: https://github.com/taiki-e/pin-project/compare/v0.4.1...v0.4.2 +[0.4.1]: https://github.com/taiki-e/pin-project/compare/v0.4.0...v0.4.1 +[0.4.0]: https://github.com/taiki-e/pin-project/compare/v0.4.0-beta.1...v0.4.0 +[0.4.0-beta.1]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.11...v0.4.0-beta.1 +[0.4.0-alpha.11]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.10...v0.4.0-alpha.11 +[0.4.0-alpha.10]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.9...v0.4.0-alpha.10 +[0.4.0-alpha.9]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.8...v0.4.0-alpha.9 +[0.4.0-alpha.8]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.7...v0.4.0-alpha.8 +[0.4.0-alpha.7]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.6...v0.4.0-alpha.7 +[0.4.0-alpha.6]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.5...v0.4.0-alpha.6 +[0.4.0-alpha.5]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.4...v0.4.0-alpha.5 +[0.4.0-alpha.4]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.3...v0.4.0-alpha.4 +[0.4.0-alpha.3]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.2...v0.4.0-alpha.3 +[0.4.0-alpha.2]: https://github.com/taiki-e/pin-project/compare/v0.4.0-alpha.1...v0.4.0-alpha.2 +[0.4.0-alpha.1]: https://github.com/taiki-e/pin-project/compare/v0.3.5...v0.4.0-alpha.1 +[0.3.5]: https://github.com/taiki-e/pin-project/compare/v0.3.4...v0.3.5 +[0.3.4]: https://github.com/taiki-e/pin-project/compare/v0.3.3...v0.3.4 +[0.3.3]: https://github.com/taiki-e/pin-project/compare/v0.3.2...v0.3.3 +[0.3.2]: https://github.com/taiki-e/pin-project/compare/v0.3.1...v0.3.2 +[0.3.1]: https://github.com/taiki-e/pin-project/compare/v0.3.0...v0.3.1 +[0.3.0]: https://github.com/taiki-e/pin-project/compare/v0.2.2...v0.3.0 +[0.2.2]: https://github.com/taiki-e/pin-project/compare/v0.2.1...v0.2.2 +[0.2.1]: https://github.com/taiki-e/pin-project/compare/v0.2.0...v0.2.1 +[0.2.0]: https://github.com/taiki-e/pin-project/compare/v0.1.8...v0.2.0 +[0.1.8]: https://github.com/taiki-e/pin-project/compare/v0.1.7...v0.1.8 +[0.1.7]: https://github.com/taiki-e/pin-project/compare/v0.1.6...v0.1.7 +[0.1.6]: https://github.com/taiki-e/pin-project/compare/v0.1.5...v0.1.6 +[0.1.5]: https://github.com/taiki-e/pin-project/compare/v0.1.4...v0.1.5 +[0.1.4]: https://github.com/taiki-e/pin-project/compare/v0.1.3...v0.1.4 +[0.1.3]: https://github.com/taiki-e/pin-project/compare/v0.1.2...v0.1.3 +[0.1.2]: https://github.com/taiki-e/pin-project/compare/v0.1.1...v0.1.2 +[0.1.1]: https://github.com/taiki-e/pin-project/compare/v0.1.0...v0.1.1 +[0.1.0]: https://github.com/taiki-e/pin-project/releases/tag/v0.1.0 diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..502ac21 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,222 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "itoa" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" + +[[package]] +name = "macrotest" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7489ae0986ce45414b7b3122c2e316661343ecf396b206e3e15f07c846616f10" +dependencies = [ + "diff", + "glob", + "prettyplease", + "serde", + "serde_json", + "syn", + "toml", +] + +[[package]] +name = "once_cell" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" + +[[package]] +name = "pin-project" +version = "1.0.12" +dependencies = [ + "macrotest", + "pin-project-internal", + "rustversion", + "static_assertions", + "trybuild", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prettyplease" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "697ae720ee02011f439e0701db107ffe2916d83f718342d65d7f8bf7b8a5fee9" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustversion" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" + +[[package]] +name = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + +[[package]] +name = "serde" +version = "1.0.143" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.143" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "syn" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "toml" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +dependencies = [ + "serde", +] + +[[package]] +name = "trybuild" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f408301c7480f9e6294eb779cfc907f54bd901a9660ef24d7f233ed5376485" +dependencies = [ + "glob", + "once_cell", + "serde", + "serde_derive", + "serde_json", + "termcolor", + "toml", +] + +[[package]] +name = "unicode-ident" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9ad85ba --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,54 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.37" +name = "pin-project" +version = "1.0.12" +exclude = [ + "/.*", + "/ci", + "/tools", +] +description = """ +A crate for safe and ergonomic pin-projection. +""" +readme = "README.md" +keywords = [ + "pin", + "macros", + "attribute", +] +categories = [ + "no-std", + "rust-patterns", +] +license = "Apache-2.0 OR MIT" +repository = "https://github.com/taiki-e/pin-project" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies.pin-project-internal] +version = "=1.0.12" + +[dev-dependencies.macrotest] +version = "1.0.9" + +[dev-dependencies.rustversion] +version = "1" + +[dev-dependencies.static_assertions] +version = "1" + +[dev-dependencies.trybuild] +version = "1.0.49" diff --git a/Cargo.toml.orig b/Cargo.toml.orig new file mode 100644 index 0000000..6ddfa42 --- /dev/null +++ b/Cargo.toml.orig @@ -0,0 +1,39 @@ +[package] +name = "pin-project" +version = "1.0.12" +edition = "2018" +rust-version = "1.37" +license = "Apache-2.0 OR MIT" +repository = "https://github.com/taiki-e/pin-project" +keywords = ["pin", "macros", "attribute"] +categories = ["no-std", "rust-patterns"] +exclude = ["/.*", "/ci", "/tools"] +description = """ +A crate for safe and ergonomic pin-projection. +""" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[workspace] +members = [ + "pin-project-internal", + "tests/auxiliary/macro", + "tests/doc", + "tests/no-core", + "tests/no-std", + "tests/rust-2015", +] + +[dependencies] +pin-project-internal = { version = "=1.0.12", path = "pin-project-internal" } + +[dev-dependencies] +pin-project-auxiliary-macro = { path = "tests/auxiliary/macro" } +macrotest = "1.0.9" +rustversion = "1" +static_assertions = "1" +trybuild = "1.0.49" + +[patch.crates-io] +prettyplease = { git = "https://github.com/taiki-e/prettyplease.git", branch = "dev" } # lower MSRV diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..f433b1a --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..0a30654 --- /dev/null +++ b/README.md @@ -0,0 +1,99 @@ +# pin-project + +[![crates.io](https://img.shields.io/crates/v/pin-project?style=flat-square&logo=rust)](https://crates.io/crates/pin-project) +[![docs.rs](https://img.shields.io/badge/docs.rs-pin--project-blue?style=flat-square&logo=docs.rs)](https://docs.rs/pin-project) +[![license](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue?style=flat-square)](#license) +[![rustc](https://img.shields.io/badge/rustc-1.37+-blue?style=flat-square&logo=rust)](https://www.rust-lang.org) +[![build status](https://img.shields.io/github/workflow/status/taiki-e/pin-project/CI/main?style=flat-square&logo=github)](https://github.com/taiki-e/pin-project/actions) + +A crate for safe and ergonomic [pin-projection]. + +## Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +pin-project = "1" +``` + +*Compiler support: requires rustc 1.37+* + +## Examples + +[`#[pin_project]`][`pin_project`] attribute creates projection types +covering all the fields of struct or enum. + +```rust +use pin_project::pin_project; +use std::pin::Pin; + +#[pin_project] +struct Struct { + #[pin] + pinned: T, + unpinned: U, +} + +impl Struct { + fn method(self: Pin<&mut Self>) { + let this = self.project(); + let _: Pin<&mut T> = this.pinned; // Pinned reference to the field + let _: &mut U = this.unpinned; // Normal reference to the field + } +} +``` + +[*code like this will be generated*][struct-default-expanded] + +To use `#[pin_project]` on enums, you need to name the projection type +returned from the method. + +```rust +use pin_project::pin_project; +use std::pin::Pin; + +#[pin_project(project = EnumProj)] +enum Enum { + Pinned(#[pin] T), + Unpinned(U), +} + +impl Enum { + fn method(self: Pin<&mut Self>) { + match self.project() { + EnumProj::Pinned(x) => { + let _: Pin<&mut T> = x; + } + EnumProj::Unpinned(y) => { + let _: &mut U = y; + } + } + } +} +``` + +[*code like this will be generated*][enum-default-expanded] + +See [documentation](https://docs.rs/pin-project) for more details, and +see [examples] directory for more examples and generated code. + +## Related Projects + +- [pin-project-lite]: A lightweight version of pin-project written with declarative macros. + +[`pin_project`]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html +[enum-default-expanded]: examples/enum-default-expanded.rs +[examples]: examples/README.md +[pin-project-lite]: https://github.com/taiki-e/pin-project-lite +[pin-projection]: https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning +[struct-default-expanded]: examples/struct-default-expanded.rs + +## License + +Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or +[MIT license](LICENSE-MIT) at your option. + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..0f30a7f --- /dev/null +++ b/examples/README.md @@ -0,0 +1,39 @@ +# Examples and generated code of each feature of pin-project + +### Basic usage of `#[pin_project]` on structs + +- [example](struct-default.rs) +- [generated code](struct-default-expanded.rs) + +### Basic usage of `#[pin_project]` on enums + +- [example](enum-default.rs) +- [generated code](enum-default-expanded.rs) + +### Manual implementation of `Unpin` by `UnsafeUnpin` + +- [example](unsafe_unpin.rs) +- [generated code](unsafe_unpin-expanded.rs) +- [`UnsafeUnpin` documentation](https://docs.rs/pin-project/1/pin_project/trait.UnsafeUnpin.html) + +### Manual implementation of `Drop` by `#[pinned_drop]` + +- [example](pinned_drop.rs) +- [generated code](pinned_drop-expanded.rs) +- [`#[pinned_drop]` documentation](https://docs.rs/pin-project/1/pin_project/attr.pinned_drop.html) + +### `project_replace()` method + +- [example](project_replace.rs) +- [generated code](project_replace-expanded.rs) +- [`project_replace()` documentation](https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#project_replace-method) + +### Ensure `!Unpin` by `#[pin_project(!Unpin)]` + +- [example](not_unpin.rs) +- [generated code](not_unpin-expanded.rs) +- [`!Unpin` documentation](https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unpin) + +Note: These generated code examples are the little simplified version of the +actual generated code. See [expansion tests](../tests#expansion-tests-expand-expandtestrs) if you +want to see the exact version of the actual generated code. diff --git a/examples/enum-default-expanded.rs b/examples/enum-default-expanded.rs new file mode 100644 index 0000000..459ca39 --- /dev/null +++ b/examples/enum-default-expanded.rs @@ -0,0 +1,101 @@ +// Original code (./enum-default.rs): +// +// ```rust +// #![allow(dead_code)] +// +// use pin_project::pin_project; +// +// #[pin_project(project = EnumProj)] +// enum Enum { +// Pinned(#[pin] T), +// Unpinned(U), +// } +// +// fn main() {} +// ``` + +#![allow(dead_code, unused_imports, unused_parens, unknown_lints, renamed_and_removed_lints)] +#![allow( + clippy::needless_lifetimes, + clippy::just_underscores_and_digits, + clippy::used_underscore_binding +)] + +use pin_project::pin_project; + +// #[pin_project(project = EnumProj)] +enum Enum { + Pinned(/* #[pin] */ T), + Unpinned(U), +} + +enum EnumProj<'pin, T, U> +where + Enum: 'pin, +{ + Pinned(::pin_project::__private::Pin<&'pin mut (T)>), + Unpinned(&'pin mut (U)), +} + +const _: () = { + // When `#[pin_project]` is used on enums, only named projection types and + // methods are generated because there is no way to access variants of + // projected types without naming it. + // (When `#[pin_project]` is used on structs, both methods are always generated.) + + impl Enum { + fn project<'pin>( + self: ::pin_project::__private::Pin<&'pin mut Self>, + ) -> EnumProj<'pin, T, U> { + unsafe { + match self.get_unchecked_mut() { + Self::Pinned(_0) => { + EnumProj::Pinned(::pin_project::__private::Pin::new_unchecked(_0)) + } + Self::Unpinned(_0) => EnumProj::Unpinned(_0), + } + } + } + } + + // Automatically create the appropriate conditional `Unpin` implementation. + // + // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/53. + // for details. + struct __Enum<'pin, T, U> { + __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin< + 'pin, + (::pin_project::__private::PhantomData, ::pin_project::__private::PhantomData), + >, + __field0: T, + } + impl<'pin, T, U> ::pin_project::__private::Unpin for Enum where + __Enum<'pin, T, U>: ::pin_project::__private::Unpin + { + } + // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it. + #[doc(hidden)] + unsafe impl<'pin, T, U> ::pin_project::UnsafeUnpin for Enum where + __Enum<'pin, T, U>: ::pin_project::__private::Unpin + { + } + + // Ensure that enum does not implement `Drop`. + // + // See ./struct-default-expanded.rs for details. + trait EnumMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl EnumMustNotImplDrop for T {} + impl EnumMustNotImplDrop for Enum {} + // A dummy impl of `PinnedDrop`, to ensure that users don't accidentally + // write a non-functional `PinnedDrop` impls. + #[doc(hidden)] + impl ::pin_project::__private::PinnedDrop for Enum { + unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} + } + + // We don't need to check for `#[repr(packed)]`, + // since it does not apply to enums. +}; + +fn main() {} diff --git a/examples/enum-default.rs b/examples/enum-default.rs new file mode 100644 index 0000000..bd3f2e6 --- /dev/null +++ b/examples/enum-default.rs @@ -0,0 +1,13 @@ +// See ./enum-default-expanded.rs for generated code. + +#![allow(dead_code)] + +use pin_project::pin_project; + +#[pin_project(project = EnumProj)] +enum Enum { + Pinned(#[pin] T), + Unpinned(U), +} + +fn main() {} diff --git a/examples/not_unpin-expanded.rs b/examples/not_unpin-expanded.rs new file mode 100644 index 0000000..5700c12 --- /dev/null +++ b/examples/not_unpin-expanded.rs @@ -0,0 +1,125 @@ +// Original code (./not_unpin.rs): +// +// ```rust +// #![allow(dead_code)] +// +// use pin_project::pin_project; +// +// #[pin_project(!Unpin)] +// pub struct Struct { +// #[pin] +// pinned: T, +// unpinned: U, +// } +// +// fn main() { +// fn _is_unpin() {} +// // _is_unpin::>(); //~ ERROR `std::marker::PhantomPinned` cannot be unpinned +// } +// ``` + +#![allow(dead_code, unused_imports, unused_parens, unknown_lints, renamed_and_removed_lints)] +#![allow(clippy::needless_lifetimes)] + +use pin_project::pin_project; + +// #[pin_project(!Unpin)] +pub struct Struct { + // #[pin] + pinned: T, + unpinned: U, +} + +const _: () = { + pub(crate) struct __StructProjection<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + } + pub(crate) struct __StructProjectionRef<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + } + + impl Struct { + pub(crate) fn project<'pin>( + self: ::pin_project::__private::Pin<&'pin mut Self>, + ) -> __StructProjection<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + __StructProjection { + pinned: ::pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + pub(crate) fn project_ref<'pin>( + self: ::pin_project::__private::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + __StructProjectionRef { + pinned: ::pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + } + + // Ensure that it's impossible to use pin projections on a #[repr(packed)] + // struct. + // + // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34 + // for details. + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + let _ = &this.pinned; + let _ = &this.unpinned; + } + + // Create `Unpin` impl that has trivial `Unpin` bounds. + // + // See https://github.com/taiki-e/pin-project/issues/102#issuecomment-540472282 + // for details. + impl<'pin, T, U> ::pin_project::__private::Unpin for Struct where + ::pin_project::__private::Wrapper<'pin, ::pin_project::__private::PhantomPinned>: + ::pin_project::__private::Unpin + { + } + // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it. + // + // To ensure that users don't accidentally write a non-functional `UnsafeUnpin` + // impls, we emit one ourselves. If the user ends up writing an `UnsafeUnpin` + // impl, they'll get a "conflicting implementations of trait" error when + // coherence checks are run. + #[doc(hidden)] + unsafe impl<'pin, T, U> ::pin_project::UnsafeUnpin for Struct where + ::pin_project::__private::Wrapper<'pin, ::pin_project::__private::PhantomPinned>: + ::pin_project::__private::Unpin + { + } + + // Ensure that struct does not implement `Drop`. + // + // See ./struct-default-expanded.rs for details. + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl StructMustNotImplDrop for T {} + impl StructMustNotImplDrop for Struct {} + // A dummy impl of `PinnedDrop`, to ensure that users don't accidentally + // write a non-functional `PinnedDrop` impls. + #[doc(hidden)] + impl ::pin_project::__private::PinnedDrop for Struct { + unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} + } +}; + +fn main() { + fn _is_unpin() {} + // _is_unpin::>(); //~ ERROR `std::marker::PhantomPinned` cannot be unpinned +} diff --git a/examples/not_unpin.rs b/examples/not_unpin.rs new file mode 100644 index 0000000..2ad72a8 --- /dev/null +++ b/examples/not_unpin.rs @@ -0,0 +1,17 @@ +// See ./not_unpin-expanded.rs for generated code. + +#![allow(dead_code)] + +use pin_project::pin_project; + +#[pin_project(!Unpin)] +pub struct Struct { + #[pin] + pinned: T, + unpinned: U, +} + +fn main() { + fn _is_unpin() {} + // _is_unpin::>(); //~ ERROR `std::marker::PhantomPinned` cannot be unpinned +} diff --git a/examples/pinned_drop-expanded.rs b/examples/pinned_drop-expanded.rs new file mode 100644 index 0000000..82207b6 --- /dev/null +++ b/examples/pinned_drop-expanded.rs @@ -0,0 +1,154 @@ +// Original code (./pinned_drop.rs): +// +// ```rust +// #![allow(dead_code)] +// +// use std::pin::Pin; +// +// use pin_project::{pin_project, pinned_drop}; +// +// #[pin_project(PinnedDrop)] +// pub struct Struct<'a, T> { +// was_dropped: &'a mut bool, +// #[pin] +// field: T, +// } +// +// #[pinned_drop] +// fn drop_Struct(mut this: Pin<&mut Struct<'_, T>>) { +// **this.project().was_dropped = true; +// } +// +// fn main() {} +// ``` + +#![allow(dead_code, unused_imports, unused_parens, unknown_lints, renamed_and_removed_lints)] +#![allow(clippy::needless_lifetimes, clippy::mut_mut)] + +use std::pin::Pin; + +use pin_project::{pin_project, pinned_drop}; + +// #[pin_project(PinnedDrop)] +pub struct Struct<'a, T> { + was_dropped: &'a mut bool, + // #[pin] + field: T, +} + +const _: () = { + pub(crate) struct __StructProjection<'pin, 'a, T> + where + Struct<'a, T>: 'pin, + { + was_dropped: &'pin mut (&'a mut bool), + field: ::pin_project::__private::Pin<&'pin mut (T)>, + } + pub(crate) struct __StructProjectionRef<'pin, 'a, T> + where + Struct<'a, T>: 'pin, + { + was_dropped: &'pin (&'a mut bool), + field: ::pin_project::__private::Pin<&'pin (T)>, + } + + impl<'a, T> Struct<'a, T> { + pub(crate) fn project<'pin>( + self: ::pin_project::__private::Pin<&'pin mut Self>, + ) -> __StructProjection<'pin, 'a, T> { + unsafe { + let Self { was_dropped, field } = self.get_unchecked_mut(); + __StructProjection { + was_dropped, + field: ::pin_project::__private::Pin::new_unchecked(field), + } + } + } + pub(crate) fn project_ref<'pin>( + self: ::pin_project::__private::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, 'a, T> { + unsafe { + let Self { was_dropped, field } = self.get_ref(); + __StructProjectionRef { + was_dropped, + field: ::pin_project::__private::Pin::new_unchecked(field), + } + } + } + } + + // Ensure that it's impossible to use pin projections on a #[repr(packed)] + // struct. + // + // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34 + // for details. + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed<'a, T>(this: &Struct<'a, T>) { + let _ = &this.was_dropped; + let _ = &this.field; + } + + impl<'a, T> ::pin_project::__private::Drop for Struct<'a, T> { + fn drop(&mut self) { + // Safety - we're in 'drop', so we know that 'self' will + // never move again. + let pinned_self = unsafe { ::pin_project::__private::Pin::new_unchecked(self) }; + // We call `pinned_drop` only once. Since `PinnedDrop::drop` + // is an unsafe method and a private API, it is never called again in safe + // code *unless the user uses a maliciously crafted macro*. + unsafe { + ::pin_project::__private::PinnedDrop::drop(pinned_self); + } + } + } + + // Automatically create the appropriate conditional `Unpin` implementation. + // + // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/53. + // for details. + pub struct __Struct<'pin, 'a, T> { + __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<'pin, (T)>, + __field0: T, + __lifetime0: &'a (), + } + impl<'pin, 'a, T> ::pin_project::__private::Unpin for Struct<'a, T> where + __Struct<'pin, 'a, T>: ::pin_project::__private::Unpin + { + } + // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it. + #[doc(hidden)] + unsafe impl<'pin, 'a, T> ::pin_project::UnsafeUnpin for Struct<'a, T> where + __Struct<'pin, 'a, T>: ::pin_project::__private::Unpin + { + } +}; + +// Implementing `PinnedDrop::drop` is safe, but calling it is not safe. +// This is because destructors can be called multiple times in safe code and +// [double dropping is unsound](https://github.com/rust-lang/rust/pull/62360). +// +// Ideally, it would be desirable to be able to forbid manual calls in +// the same way as `Drop::drop`, but the library cannot do it. So, by using +// macros and replacing them with private traits, we prevent users from +// calling `PinnedDrop::drop`. +// +// Users can implement [`Drop`] safely using `#[pinned_drop]` and can drop a +// type that implements `PinnedDrop` using the [`drop`] function safely. +// **Do not call or implement this trait directly.** +#[doc(hidden)] +impl ::pin_project::__private::PinnedDrop for Struct<'_, T> { + // Since calling it twice on the same object would be UB, + // this method is unsafe. + unsafe fn drop(self: Pin<&mut Self>) { + #[allow(clippy::needless_pass_by_value)] + fn __drop_inner(__self: Pin<&mut Struct<'_, T>>) { + // A dummy `__drop_inner` function to prevent users call outer `__drop_inner`. + fn __drop_inner() {} + + **__self.project().was_dropped = true; + } + __drop_inner(self); + } +} + +fn main() {} diff --git a/examples/pinned_drop.rs b/examples/pinned_drop.rs new file mode 100644 index 0000000..6fb8719 --- /dev/null +++ b/examples/pinned_drop.rs @@ -0,0 +1,23 @@ +// See ./pinned_drop-expanded.rs for generated code. + +#![allow(dead_code)] + +use std::pin::Pin; + +use pin_project::{pin_project, pinned_drop}; + +#[pin_project(PinnedDrop)] +pub struct Struct<'a, T> { + was_dropped: &'a mut bool, + #[pin] + field: T, +} + +#[pinned_drop] +impl PinnedDrop for Struct<'_, T> { + fn drop(self: Pin<&mut Self>) { + **self.project().was_dropped = true; + } +} + +fn main() {} diff --git a/examples/project_replace-expanded.rs b/examples/project_replace-expanded.rs new file mode 100644 index 0000000..445e570 --- /dev/null +++ b/examples/project_replace-expanded.rs @@ -0,0 +1,156 @@ +// Original code (./struct-default.rs): +// +// ```rust +// #![allow(dead_code)] +// +// use pin_project::pin_project; +// +// #[pin_project(project_replace)] +// struct Struct { +// #[pin] +// pinned: T, +// unpinned: U, +// } +// +// fn main() {} +// ``` + +#![allow(dead_code, unused_imports, unused_parens, unknown_lints, renamed_and_removed_lints)] +#![allow(clippy::needless_lifetimes)] + +use pin_project::pin_project; + +// #[pin_project(project_replace)] +struct Struct { + // #[pin] + pinned: T, + unpinned: U, +} + +const _: () = { + struct __StructProjection<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + } + struct __StructProjectionRef<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + } + struct __StructProjectionOwned { + pinned: ::pin_project::__private::PhantomData, + unpinned: U, + } + + impl Struct { + fn project<'pin>( + self: ::pin_project::__private::Pin<&'pin mut Self>, + ) -> __StructProjection<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + __StructProjection { + pinned: ::pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + fn project_ref<'pin>( + self: ::pin_project::__private::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + __StructProjectionRef { + pinned: ::pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + fn project_replace( + self: ::pin_project::__private::Pin<&mut Self>, + __replacement: Self, + ) -> __StructProjectionOwned { + unsafe { + let __self_ptr: *mut Self = self.get_unchecked_mut(); + + // Destructors will run in reverse order, so next create a guard to overwrite + // `self` with the replacement value without calling destructors. + let __guard = + ::pin_project::__private::UnsafeOverwriteGuard::new(__self_ptr, __replacement); + + let Self { pinned, unpinned } = &mut *__self_ptr; + + // First, extract all the unpinned fields + let __result = __StructProjectionOwned { + pinned: ::pin_project::__private::PhantomData, + unpinned: ::pin_project::__private::ptr::read(unpinned), + }; + + // Now create guards to drop all the pinned fields + // + // Due to a compiler bug (https://github.com/rust-lang/rust/issues/47949) + // this must be in its own scope, or else `__result` will not be dropped + // if any of the destructors panic. + { + let __guard = ::pin_project::__private::UnsafeDropInPlaceGuard::new(pinned); + } + + // Finally, return the result + __result + } + } + } + + // Ensure that it's impossible to use pin projections on a #[repr(packed)] + // struct. + // + // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34 + // for details. + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + let _ = &this.pinned; + let _ = &this.unpinned; + } + + // Automatically create the appropriate conditional `Unpin` implementation. + // + // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/53. + // for details. + struct __Struct<'pin, T, U> { + __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin< + 'pin, + (::pin_project::__private::PhantomData, ::pin_project::__private::PhantomData), + >, + __field0: T, + } + impl<'pin, T, U> ::pin_project::__private::Unpin for Struct where + __Struct<'pin, T, U>: ::pin_project::__private::Unpin + { + } + // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it. + #[doc(hidden)] + unsafe impl<'pin, T, U> ::pin_project::UnsafeUnpin for Struct where + __Struct<'pin, T, U>: ::pin_project::__private::Unpin + { + } + + // Ensure that struct does not implement `Drop`. + // + // See ./struct-default-expanded.rs for details. + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl StructMustNotImplDrop for T {} + impl StructMustNotImplDrop for Struct {} + // A dummy impl of `PinnedDrop`, to ensure that users don't accidentally + // write a non-functional `PinnedDrop` impls. + #[doc(hidden)] + impl ::pin_project::__private::PinnedDrop for Struct { + unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} + } +}; + +fn main() {} diff --git a/examples/project_replace.rs b/examples/project_replace.rs new file mode 100644 index 0000000..99cec18 --- /dev/null +++ b/examples/project_replace.rs @@ -0,0 +1,14 @@ +// See ./struct-default-expanded.rs for generated code. + +#![allow(dead_code)] + +use pin_project::pin_project; + +#[pin_project(project_replace)] +struct Struct { + #[pin] + pinned: T, + unpinned: U, +} + +fn main() {} diff --git a/examples/struct-default-expanded.rs b/examples/struct-default-expanded.rs new file mode 100644 index 0000000..d661099 --- /dev/null +++ b/examples/struct-default-expanded.rs @@ -0,0 +1,155 @@ +// Original code (./struct-default.rs): +// +// ```rust +// #![allow(dead_code)] +// +// use pin_project::pin_project; +// +// #[pin_project] +// struct Struct { +// #[pin] +// pinned: T, +// unpinned: U, +// } +// +// fn main() {} +// ``` + +#![allow(dead_code, unused_imports, unused_parens, unknown_lints, renamed_and_removed_lints)] +#![allow(clippy::needless_lifetimes)] + +use pin_project::pin_project; + +// #[pin_project] +struct Struct { + // #[pin] + pinned: T, + unpinned: U, +} + +const _: () = { + struct __StructProjection<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + } + struct __StructProjectionRef<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + } + + impl Struct { + fn project<'pin>( + self: ::pin_project::__private::Pin<&'pin mut Self>, + ) -> __StructProjection<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + __StructProjection { + pinned: ::pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + fn project_ref<'pin>( + self: ::pin_project::__private::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + __StructProjectionRef { + pinned: ::pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + } + + // Ensure that it's impossible to use pin projections on a #[repr(packed)] + // struct. + // + // Taking a reference to a packed field is UB, and applying + // `#[forbid(unaligned_references)]` makes sure that doing this is a hard error. + // + // If the struct ends up having #[repr(packed)] applied somehow, + // this will generate an (unfriendly) error message. Under all reasonable + // circumstances, we'll detect the #[repr(packed)] attribute, and generate + // a much nicer error above. + // + // See https://github.com/taiki-e/pin-project/pull/34 for more details. + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + let _ = &this.pinned; + let _ = &this.unpinned; + } + + // Automatically create the appropriate conditional `Unpin` implementation. + // + // Basically this is equivalent to the following code: + // + // ```rust + // impl Unpin for Struct where T: Unpin {} + // ``` + // + // However, if struct is public and there is a private type field, + // this would cause an E0446 (private type in public interface). + // + // When RFC 2145 is implemented (rust-lang/rust#48054), + // this will become a lint, rather then a hard error. + // + // As a workaround for this, we generate a new struct, containing all of + // the pinned fields from our #[pin_project] type. This struct is declared + // within a function, which makes it impossible to be named by user code. + // This guarantees that it will use the default auto-trait impl for Unpin - + // that is, it will implement Unpin iff all of its fields implement Unpin. + // This type can be safely declared as 'public', satisfying the privacy + // checker without actually allowing user code to access it. + // + // This allows users to apply the #[pin_project] attribute to types + // regardless of the privacy of the types of their fields. + // + // See also https://github.com/taiki-e/pin-project/pull/53. + struct __Struct<'pin, T, U> { + __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin< + 'pin, + (::pin_project::__private::PhantomData, ::pin_project::__private::PhantomData), + >, + __field0: T, + } + impl<'pin, T, U> ::pin_project::__private::Unpin for Struct where + __Struct<'pin, T, U>: ::pin_project::__private::Unpin + { + } + // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it. + // + // To ensure that users don't accidentally write a non-functional `UnsafeUnpin` + // impls, we emit one ourselves. If the user ends up writing an `UnsafeUnpin` + // impl, they'll get a "conflicting implementations of trait" error when + // coherence checks are run. + #[doc(hidden)] + unsafe impl<'pin, T, U> ::pin_project::UnsafeUnpin for Struct where + __Struct<'pin, T, U>: ::pin_project::__private::Unpin + { + } + + // Ensure that struct does not implement `Drop`. + // + // If you attempt to provide an Drop impl, the blanket impl will + // then apply to your type, causing a compile-time error due to + // the conflict with the second impl. + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl StructMustNotImplDrop for T {} + impl StructMustNotImplDrop for Struct {} + // A dummy impl of `PinnedDrop`, to ensure that users don't accidentally + // write a non-functional `PinnedDrop` impls. + #[doc(hidden)] + impl ::pin_project::__private::PinnedDrop for Struct { + unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} + } +}; + +fn main() {} diff --git a/examples/struct-default.rs b/examples/struct-default.rs new file mode 100644 index 0000000..46808a5 --- /dev/null +++ b/examples/struct-default.rs @@ -0,0 +1,14 @@ +// See ./struct-default-expanded.rs for generated code. + +#![allow(dead_code)] + +use pin_project::pin_project; + +#[pin_project] +struct Struct { + #[pin] + pinned: T, + unpinned: U, +} + +fn main() {} diff --git a/examples/unsafe_unpin-expanded.rs b/examples/unsafe_unpin-expanded.rs new file mode 100644 index 0000000..e9c7abc --- /dev/null +++ b/examples/unsafe_unpin-expanded.rs @@ -0,0 +1,107 @@ +// Original code (./unsafe_unpin.rs): +// +// ```rust +// #![allow(dead_code)] +// +// use pin_project::{pin_project, UnsafeUnpin}; +// +// #[pin_project(UnsafeUnpin)] +// pub struct Struct { +// #[pin] +// pinned: T, +// unpinned: U, +// } +// +// unsafe impl UnsafeUnpin for Struct {} +// +// fn main() {} +// ``` + +#![allow(dead_code, unused_imports, unused_parens, unknown_lints, renamed_and_removed_lints)] +#![allow(clippy::needless_lifetimes)] + +use pin_project::{pin_project, UnsafeUnpin}; + +// #[pin_project(UnsafeUnpin)] +pub struct Struct { + // #[pin] + pinned: T, + unpinned: U, +} + +const _: () = { + pub(crate) struct __StructProjection<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + } + pub(crate) struct __StructProjectionRef<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + } + + impl Struct { + pub(crate) fn project<'pin>( + self: ::pin_project::__private::Pin<&'pin mut Self>, + ) -> __StructProjection<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + __StructProjection { + pinned: ::pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + pub(crate) fn project_ref<'pin>( + self: ::pin_project::__private::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + __StructProjectionRef { + pinned: ::pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + } + + // Ensure that it's impossible to use pin projections on a #[repr(packed)] + // struct. + // + // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34 + // for details. + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + let _ = &this.pinned; + let _ = &this.unpinned; + } + + // Implement `Unpin` via `UnsafeUnpin`. + impl<'pin, T, U> ::pin_project::__private::Unpin for Struct where + ::pin_project::__private::Wrapper<'pin, Self>: ::pin_project::UnsafeUnpin + { + } + + // Ensure that struct does not implement `Drop`. + // + // See ./struct-default-expanded.rs for details. + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl StructMustNotImplDrop for T {} + impl StructMustNotImplDrop for Struct {} + // A dummy impl of `PinnedDrop`, to ensure that users don't accidentally + // write a non-functional `PinnedDrop` impls. + #[doc(hidden)] + impl ::pin_project::__private::PinnedDrop for Struct { + unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} + } +}; + +unsafe impl UnsafeUnpin for Struct {} + +fn main() {} diff --git a/examples/unsafe_unpin.rs b/examples/unsafe_unpin.rs new file mode 100644 index 0000000..5ec0cd2 --- /dev/null +++ b/examples/unsafe_unpin.rs @@ -0,0 +1,16 @@ +// See ./unsafe_unpin-expanded.rs for generated code. + +#![allow(dead_code)] + +use pin_project::{pin_project, UnsafeUnpin}; + +#[pin_project(UnsafeUnpin)] +pub struct Struct { + #[pin] + pinned: T, + unpinned: U, +} + +unsafe impl UnsafeUnpin for Struct {} + +fn main() {} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..5fa9298 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,315 @@ +//! A crate for safe and ergonomic [pin-projection]. +//! +//! # Examples +//! +//! [`#[pin_project]`][`pin_project`] attribute creates projection types +//! covering all the fields of struct or enum. +//! +//! ```rust +//! use std::pin::Pin; +//! +//! use pin_project::pin_project; +//! +//! #[pin_project] +//! struct Struct { +//! #[pin] +//! pinned: T, +//! unpinned: U, +//! } +//! +//! impl Struct { +//! fn method(self: Pin<&mut Self>) { +//! let this = self.project(); +//! let _: Pin<&mut T> = this.pinned; // Pinned reference to the field +//! let _: &mut U = this.unpinned; // Normal reference to the field +//! } +//! } +//! ``` +//! +//! [*code like this will be generated*][struct-default-expanded] +//! +//! To use `#[pin_project]` on enums, you need to name the projection type +//! returned from the method. +//! +//! ```rust +//! use std::pin::Pin; +//! +//! use pin_project::pin_project; +//! +//! #[pin_project(project = EnumProj)] +//! enum Enum { +//! Pinned(#[pin] T), +//! Unpinned(U), +//! } +//! +//! impl Enum { +//! fn method(self: Pin<&mut Self>) { +//! match self.project() { +//! EnumProj::Pinned(x) => { +//! let _: Pin<&mut T> = x; +//! } +//! EnumProj::Unpinned(y) => { +//! let _: &mut U = y; +//! } +//! } +//! } +//! } +//! ``` +//! +//! [*code like this will be generated*][enum-default-expanded] +//! +//! See [`#[pin_project]`][`pin_project`] attribute for more details, and +//! see [examples] directory for more examples and generated code. +//! +//! [examples]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/README.md +//! [enum-default-expanded]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/enum-default-expanded.rs +//! [pin-projection]: core::pin#projections-and-structural-pinning +//! [struct-default-expanded]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/struct-default-expanded.rs + +#![no_std] +#![doc(test( + no_crate_inject, + attr( + deny(warnings, rust_2018_idioms, single_use_lifetimes), + allow(dead_code, unused_variables) + ) +))] +#![warn(missing_docs, rust_2018_idioms, single_use_lifetimes, unreachable_pub)] +#![warn( + clippy::pedantic, + // lints for public library + clippy::alloc_instead_of_core, + clippy::exhaustive_enums, + clippy::exhaustive_structs, + clippy::std_instead_of_alloc, + clippy::std_instead_of_core, + // lints that help writing unsafe code + clippy::default_union_representation, + clippy::trailing_empty_array, + clippy::transmute_undefined_repr, + clippy::undocumented_unsafe_blocks, +)] +#![allow(clippy::needless_doctest_main)] + +#[doc(inline)] +pub use pin_project_internal::pin_project; +#[doc(inline)] +pub use pin_project_internal::pinned_drop; + +/// A trait used for custom implementations of [`Unpin`]. +/// +/// This trait is used in conjunction with the `UnsafeUnpin` argument to +/// the [`#[pin_project]`][macro@pin_project] attribute. +/// +/// # Safety +/// +/// The Rust [`Unpin`] trait is safe to implement - by itself, +/// implementing it cannot lead to [undefined behavior][undefined-behavior]. +/// Undefined behavior can only occur when other unsafe code is used. +/// +/// It turns out that using pin projections, which requires unsafe code, +/// imposes additional requirements on an [`Unpin`] impl. Normally, all of this +/// unsafety is contained within this crate, ensuring that it's impossible for +/// you to violate any of the guarantees required by pin projection. +/// +/// However, things change if you want to provide a custom [`Unpin`] impl +/// for your `#[pin_project]` type. As stated in [the Rust +/// documentation][pin-projection], you must be sure to only implement [`Unpin`] +/// when all of your `#[pin]` fields (i.e. structurally pinned fields) are also +/// [`Unpin`]. +/// +/// To help highlight this unsafety, the `UnsafeUnpin` trait is provided. +/// Implementing this trait is logically equivalent to implementing [`Unpin`] - +/// this crate will generate an [`Unpin`] impl for your type that 'forwards' to +/// your `UnsafeUnpin` impl. However, this trait is `unsafe` - since your type +/// uses structural pinning (otherwise, you wouldn't be using this crate!), +/// you must be sure that your `UnsafeUnpin` impls follows all of +/// the requirements for an [`Unpin`] impl of a structurally-pinned type. +/// +/// Note that if you specify `#[pin_project(UnsafeUnpin)]`, but do *not* +/// provide an impl of `UnsafeUnpin`, your type will never implement [`Unpin`]. +/// This is effectively the same thing as adding a [`PhantomPinned`] to your +/// type. +/// +/// Since this trait is `unsafe`, impls of it will be detected by the +/// `unsafe_code` lint, and by tools like [`cargo geiger`][cargo-geiger]. +/// +/// # Examples +/// +/// An `UnsafeUnpin` impl which, in addition to requiring that structurally +/// pinned fields be [`Unpin`], imposes an additional requirement: +/// +/// ```rust +/// use pin_project::{pin_project, UnsafeUnpin}; +/// +/// #[pin_project(UnsafeUnpin)] +/// struct Struct { +/// #[pin] +/// field_1: K, +/// field_2: V, +/// } +/// +/// unsafe impl UnsafeUnpin for Struct where K: Unpin + Clone {} +/// ``` +/// +/// [`PhantomPinned`]: core::marker::PhantomPinned +/// [cargo-geiger]: https://github.com/rust-secure-code/cargo-geiger +/// [pin-projection]: core::pin#projections-and-structural-pinning +/// [undefined-behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html +pub unsafe trait UnsafeUnpin {} + +// Not public API. +#[doc(hidden)] +pub mod __private { + use core::mem::ManuallyDrop; + #[doc(hidden)] + pub use core::{ + marker::{PhantomData, PhantomPinned, Unpin}, + ops::Drop, + pin::Pin, + ptr, + }; + + #[doc(hidden)] + pub use pin_project_internal::__PinProjectInternalDerive; + + use super::UnsafeUnpin; + + // An internal trait used for custom implementations of [`Drop`]. + // + // **Do not call or implement this trait directly.** + // + // # Why this trait is private and `#[pinned_drop]` attribute is needed? + // + // Implementing `PinnedDrop::drop` is safe, but calling it is not safe. + // This is because destructors can be called multiple times in safe code and + // [double dropping is unsound][rust-lang/rust#62360]. + // + // Ideally, it would be desirable to be able to forbid manual calls in + // the same way as [`Drop::drop`], but the library cannot do it. So, by using + // macros and replacing them with private traits, + // this crate prevent users from calling `PinnedDrop::drop` in safe code. + // + // This allows implementing [`Drop`] safely using `#[pinned_drop]`. + // Also by using the [`drop`] function just like dropping a type that directly + // implements [`Drop`], can drop safely a type that implements `PinnedDrop`. + // + // [rust-lang/rust#62360]: https://github.com/rust-lang/rust/pull/62360 + #[doc(hidden)] + pub trait PinnedDrop { + #[doc(hidden)] + unsafe fn drop(self: Pin<&mut Self>); + } + + // This is an internal helper struct used by `pin-project-internal`. + // This allows us to force an error if the user tries to provide + // a regular `Unpin` impl when they specify the `UnsafeUnpin` argument. + // This is why we need Wrapper: + // + // Supposed we have the following code: + // + // ```rust + // #[pin_project(UnsafeUnpin)] + // struct MyStruct { + // #[pin] field: T + // } + // + // impl Unpin for MyStruct where MyStruct: UnsafeUnpin {} // generated by pin-project-internal + // impl Unpin for MyStruct where T: Copy // written by the user + // ``` + // + // We want this code to be rejected - the user is completely bypassing + // `UnsafeUnpin`, and providing an unsound Unpin impl in safe code! + // + // Unfortunately, the Rust compiler will accept the above code. + // Because MyStruct is declared in the same crate as the user-provided impl, + // the compiler will notice that `MyStruct: UnsafeUnpin` never holds. + // + // The solution is to introduce the `Wrapper` struct, which is defined + // in the `pin-project` crate. + // + // We now have code that looks like this: + // + // ```rust + // impl Unpin for MyStruct where Wrapper>: UnsafeUnpin {} // generated by pin-project-internal + // impl Unpin for MyStruct where T: Copy // written by the user + // ``` + // + // We also have `unsafe impl UnsafeUnpin for Wrapper where T: UnsafeUnpin {}` + // in the `pin-project` crate. + // + // Now, our generated impl has a bound involving a type defined in another + // crate - Wrapper. This will cause rust to conservatively assume that + // `Wrapper>: UnsafeUnpin` holds, in the interest of preserving + // forwards compatibility (in case such an impl is added for Wrapper in + // a new version of the crate). + // + // This will cause rust to reject any other `Unpin` impls for MyStruct, + // since it will assume that our generated impl could potentially apply in + // any situation. + // + // This achieves the desired effect - when the user writes + // `#[pin_project(UnsafeUnpin)]`, the user must either provide no impl of + // `UnsafeUnpin` (which is equivalent to making the type never implement + // Unpin), or provide an impl of `UnsafeUnpin`. It is impossible for them to + // provide an impl of `Unpin` + #[doc(hidden)] + pub struct Wrapper<'a, T: ?Sized>(PhantomData<&'a ()>, T); + + // SAFETY: `T` implements UnsafeUnpin. + unsafe impl UnsafeUnpin for Wrapper<'_, T> {} + + // This is an internal helper struct used by `pin-project-internal`. + // + // See https://github.com/taiki-e/pin-project/pull/53 for more details. + #[doc(hidden)] + pub struct AlwaysUnpin<'a, T>(PhantomData<&'a ()>, PhantomData); + + impl Unpin for AlwaysUnpin<'_, T> {} + + // This is an internal helper used to ensure a value is dropped. + #[doc(hidden)] + pub struct UnsafeDropInPlaceGuard(*mut T); + + impl UnsafeDropInPlaceGuard { + #[doc(hidden)] + pub unsafe fn new(ptr: *mut T) -> Self { + Self(ptr) + } + } + + impl Drop for UnsafeDropInPlaceGuard { + fn drop(&mut self) { + // SAFETY: the caller of `UnsafeDropInPlaceGuard::new` must guarantee + // that `ptr` is valid for drop when this guard is destructed. + unsafe { + ptr::drop_in_place(self.0); + } + } + } + + // This is an internal helper used to ensure a value is overwritten without + // its destructor being called. + #[doc(hidden)] + pub struct UnsafeOverwriteGuard { + target: *mut T, + value: ManuallyDrop, + } + + impl UnsafeOverwriteGuard { + #[doc(hidden)] + pub unsafe fn new(target: *mut T, value: T) -> Self { + Self { target, value: ManuallyDrop::new(value) } + } + } + + impl Drop for UnsafeOverwriteGuard { + fn drop(&mut self) { + // SAFETY: the caller of `UnsafeOverwriteGuard::new` must guarantee + // that `target` is valid for writes when this guard is destructed. + unsafe { + ptr::write(self.target, ptr::read(&*self.value)); + } + } + } +} diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..b109e71 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,44 @@ +# Tests + +To run all tests, run the following command: + +```sh +cargo +nightly test --all +``` + +## UI tests (`ui`, `compiletest.rs`) + +This checks errors detected by the macro or the Rust compiler in the resulting +expanded code. + +To run this test, run the following command: + +```sh +cargo +nightly test --test compiletest +``` + +Locally, this test updates the files in the `ui` directory if there are +changes to the generated code. If there are any changes to the files in the +`ui` directory after running the test, please commit them. + +See also [`trybuild` documentation](https://docs.rs/trybuild). + +## Expansion tests (`expand`, `expandtest.rs`) + +Similar to ui tests, but instead of checking the compiler output, this checks +the code generated by macros. + +See [examples](../examples/README.md) for descriptions of what the generated +code does, and why it needs to be generated. + +To run this test, run the following command: + +```sh +cargo +nightly test --test expandtest +``` + +Locally, this test updates the files in the `expand` directory if there are +changes to the generated code. If there are any changes to the files in the +`expand` directory after running the test, please commit them. + +See also [`macrotest` documentation](https://docs.rs/macrotest). diff --git a/tests/auxiliary/mod.rs b/tests/auxiliary/mod.rs new file mode 100644 index 0000000..1457099 --- /dev/null +++ b/tests/auxiliary/mod.rs @@ -0,0 +1,12 @@ +#![allow(dead_code, unused_macros)] + +macro_rules! assert_unpin { + ($ty:ty) => { + static_assertions::assert_impl_all!($ty: Unpin); + }; +} +macro_rules! assert_not_unpin { + ($ty:ty) => { + static_assertions::assert_not_impl_all!($ty: Unpin); + }; +} diff --git a/tests/cfg.rs b/tests/cfg.rs new file mode 100644 index 0000000..2f5387b --- /dev/null +++ b/tests/cfg.rs @@ -0,0 +1,184 @@ +#![warn(rust_2018_idioms, single_use_lifetimes)] +#![allow(dead_code)] + +// Refs: https://doc.rust-lang.org/reference/attributes.html + +#[macro_use] +mod auxiliary; + +use std::{marker::PhantomPinned, pin::Pin}; + +use pin_project::pin_project; + +struct Always; + +// Use this type to check that `cfg(any())` is working properly. +struct Never(PhantomPinned); + +#[test] +fn cfg() { + // structs + + #[pin_project(project_replace)] + struct SameName { + #[cfg(not(any()))] + #[pin] + inner: Always, + #[cfg(any())] + #[pin] + inner: Never, + } + + assert_unpin!(SameName); + + let _ = SameName { inner: Always }; + + #[pin_project(project_replace)] + struct DifferentName { + #[cfg(not(any()))] + #[pin] + a: Always, + #[cfg(any())] + #[pin] + n: Never, + } + + assert_unpin!(DifferentName); + + let _ = DifferentName { a: Always }; + + #[pin_project(project_replace)] + struct TupleStruct( + #[cfg(not(any()))] + #[pin] + Always, + #[cfg(any())] + #[pin] + Never, + ); + + assert_unpin!(TupleStruct); + + let _ = TupleStruct(Always); + + // enums + + #[pin_project( + project = VariantProj, + project_ref = VariantProjRef, + project_replace = VariantProjOwn, + )] + enum Variant { + #[cfg(not(any()))] + Inner(#[pin] Always), + #[cfg(any())] + Inner(#[pin] Never), + + #[cfg(not(any()))] + A(#[pin] Always), + #[cfg(any())] + N(#[pin] Never), + } + + assert_unpin!(Variant); + + let _ = Variant::Inner(Always); + let _ = Variant::A(Always); + + #[pin_project( + project = FieldProj, + project_ref = FieldProjRef, + project_replace = FieldProjOwn, + )] + enum Field { + SameName { + #[cfg(not(any()))] + #[pin] + inner: Always, + #[cfg(any())] + #[pin] + inner: Never, + }, + DifferentName { + #[cfg(not(any()))] + #[pin] + a: Always, + #[cfg(any())] + #[pin] + n: Never, + }, + TupleVariant( + #[cfg(not(any()))] + #[pin] + Always, + #[cfg(any())] + #[pin] + Never, + ), + } + + assert_unpin!(Field); + + let _ = Field::SameName { inner: Always }; + let _ = Field::DifferentName { a: Always }; + let _ = Field::TupleVariant(Always); +} + +#[test] +fn cfg_attr() { + #[pin_project(project_replace)] + struct SameCfg { + #[cfg(not(any()))] + #[cfg_attr(not(any()), pin)] + inner: Always, + #[cfg(any())] + #[cfg_attr(any(), pin)] + inner: Never, + } + + assert_unpin!(SameCfg); + + let mut x = SameCfg { inner: Always }; + let x = Pin::new(&mut x).project(); + let _: Pin<&mut Always> = x.inner; + + #[pin_project(project_replace)] + struct DifferentCfg { + #[cfg(not(any()))] + #[cfg_attr(any(), pin)] + inner: Always, + #[cfg(any())] + #[cfg_attr(not(any()), pin)] + inner: Never, + } + + assert_unpin!(DifferentCfg); + + let mut x = DifferentCfg { inner: Always }; + let x = Pin::new(&mut x).project(); + let _: &mut Always = x.inner; + + #[cfg_attr(not(any()), pin_project)] + struct Foo { + #[cfg_attr(not(any()), pin)] + inner: T, + } + + assert_unpin!(Foo<()>); + assert_not_unpin!(Foo); + + let mut x = Foo { inner: 0_u8 }; + let x = Pin::new(&mut x).project(); + let _: Pin<&mut u8> = x.inner; +} + +#[test] +fn cfg_attr_any_packed() { + // Since `cfg(any())` can never be true, it is okay for this to pass. + #[pin_project(project_replace)] + #[cfg_attr(any(), repr(packed))] + struct Struct { + #[pin] + f: u32, + } +} diff --git a/tests/compiletest.rs b/tests/compiletest.rs new file mode 100644 index 0000000..b06e1e8 --- /dev/null +++ b/tests/compiletest.rs @@ -0,0 +1,16 @@ +#![cfg(not(miri))] +#![warn(rust_2018_idioms, single_use_lifetimes)] + +use std::env; + +#[rustversion::attr(not(nightly), ignore)] +#[test] +fn ui() { + if env::var_os("CI").is_none() { + env::set_var("TRYBUILD", "overwrite"); + } + + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/**/*.rs"); + t.pass("tests/run-pass/**/*.rs"); +} diff --git a/tests/drop_order.rs b/tests/drop_order.rs new file mode 100644 index 0000000..8ced56e --- /dev/null +++ b/tests/drop_order.rs @@ -0,0 +1,162 @@ +#![warn(rust_2018_idioms, single_use_lifetimes)] + +// Refs: https://doc.rust-lang.org/reference/destructors.html + +use std::{cell::Cell, pin::Pin, thread}; + +use pin_project::pin_project; + +struct D<'a>(&'a Cell, usize); + +impl Drop for D<'_> { + fn drop(&mut self) { + if !thread::panicking() { + let old = self.0.replace(self.1); + assert_eq!(old, self.1 - 1); + } + } +} + +#[pin_project(project_replace)] +struct StructPinned<'a> { + #[pin] + f1: D<'a>, + #[pin] + f2: D<'a>, +} + +#[pin_project(project_replace)] +struct StructUnpinned<'a> { + f1: D<'a>, + f2: D<'a>, +} + +#[pin_project(project_replace)] +struct TuplePinned<'a>(#[pin] D<'a>, #[pin] D<'a>); + +#[pin_project(project_replace)] +struct TupleUnpinned<'a>(D<'a>, D<'a>); + +#[pin_project(project_replace = EnumProj)] +enum Enum<'a> { + #[allow(dead_code)] // false positive that fixed in Rust 1.38 + StructPinned { + #[pin] + f1: D<'a>, + #[pin] + f2: D<'a>, + }, + #[allow(dead_code)] // false positive that fixed in Rust 1.38 + StructUnpinned { + f1: D<'a>, + f2: D<'a>, + }, + TuplePinned(#[pin] D<'a>, #[pin] D<'a>), + TupleUnpinned(D<'a>, D<'a>), +} + +#[test] +fn struct_pinned() { + { + let c = Cell::new(0); + let _x = StructPinned { f1: D(&c, 1), f2: D(&c, 2) }; + } + { + let c = Cell::new(0); + let mut x = StructPinned { f1: D(&c, 1), f2: D(&c, 2) }; + let y = Pin::new(&mut x); + let _z = y.project_replace(StructPinned { f1: D(&c, 3), f2: D(&c, 4) }); + } +} + +#[test] +fn struct_unpinned() { + { + let c = Cell::new(0); + let _x = StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) }; + } + { + let c = Cell::new(0); + let mut x = StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) }; + let y = Pin::new(&mut x); + let _z = y.project_replace(StructUnpinned { f1: D(&c, 3), f2: D(&c, 4) }); + } +} + +#[test] +fn tuple_pinned() { + { + let c = Cell::new(0); + let _x = TuplePinned(D(&c, 1), D(&c, 2)); + } + { + let c = Cell::new(0); + let mut x = TuplePinned(D(&c, 1), D(&c, 2)); + let y = Pin::new(&mut x); + let _z = y.project_replace(TuplePinned(D(&c, 3), D(&c, 4))); + } +} + +#[test] +fn tuple_unpinned() { + { + let c = Cell::new(0); + let _x = TupleUnpinned(D(&c, 1), D(&c, 2)); + } + { + let c = Cell::new(0); + let mut x = TupleUnpinned(D(&c, 1), D(&c, 2)); + let y = Pin::new(&mut x); + let _z = y.project_replace(TupleUnpinned(D(&c, 3), D(&c, 4))); + } +} + +#[test] +fn enum_struct() { + { + let c = Cell::new(0); + let _x = Enum::StructPinned { f1: D(&c, 1), f2: D(&c, 2) }; + } + { + let c = Cell::new(0); + let mut x = Enum::StructPinned { f1: D(&c, 1), f2: D(&c, 2) }; + let y = Pin::new(&mut x); + let _z = y.project_replace(Enum::StructPinned { f1: D(&c, 3), f2: D(&c, 4) }); + } + + { + let c = Cell::new(0); + let _x = Enum::StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) }; + } + { + let c = Cell::new(0); + let mut x = Enum::StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) }; + let y = Pin::new(&mut x); + let _z = y.project_replace(Enum::StructUnpinned { f1: D(&c, 3), f2: D(&c, 4) }); + } +} + +#[test] +fn enum_tuple() { + { + let c = Cell::new(0); + let _x = Enum::TuplePinned(D(&c, 1), D(&c, 2)); + } + { + let c = Cell::new(0); + let mut x = Enum::TuplePinned(D(&c, 1), D(&c, 2)); + let y = Pin::new(&mut x); + let _z = y.project_replace(Enum::TuplePinned(D(&c, 3), D(&c, 4))); + } + + { + let c = Cell::new(0); + let _x = Enum::TupleUnpinned(D(&c, 1), D(&c, 2)); + } + { + let c = Cell::new(0); + let mut x = Enum::TupleUnpinned(D(&c, 1), D(&c, 2)); + let y = Pin::new(&mut x); + let _z = y.project_replace(Enum::TupleUnpinned(D(&c, 3), D(&c, 4))); + } +} diff --git a/tests/expand/default/enum.expanded.rs b/tests/expand/default/enum.expanded.rs new file mode 100644 index 0000000..490bf2e --- /dev/null +++ b/tests/expand/default/enum.expanded.rs @@ -0,0 +1,145 @@ +use pin_project::pin_project; +#[pin(__private(project = EnumProj, project_ref = EnumProjRef))] +enum Enum { + Struct { #[pin] pinned: T, unpinned: U }, + Tuple(#[pin] T, U), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::mut_mut)] +enum EnumProj<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + }, + Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::ref_option_ref)] +enum EnumProjRef<'pin, T, U> +where + Enum: 'pin, +{ + Struct { pinned: ::pin_project::__private::Pin<&'pin (T)>, unpinned: &'pin (U) }, + Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + impl Enum { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> EnumProj<'pin, T, U> { + unsafe { + match self.get_unchecked_mut() { + Self::Struct { pinned, unpinned } => { + EnumProj::Struct { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + Self::Tuple(_0, _1) => { + EnumProj::Tuple( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + Self::Unit => EnumProj::Unit, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> EnumProjRef<'pin, T, U> { + unsafe { + match self.get_ref() { + Self::Struct { pinned, unpinned } => { + EnumProjRef::Struct { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + Self::Tuple(_0, _1) => { + EnumProjRef::Tuple( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + Self::Unit => EnumProjRef::Unit, + } + } + } + } + #[allow(missing_debug_implementations)] + struct __Enum<'pin, T, U> { + __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< + 'pin, + ( + _pin_project::__private::PhantomData, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + __field1: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait EnumMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl EnumMustNotImplDrop for T {} + impl EnumMustNotImplDrop for Enum {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Enum { + 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 { + 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..0005d86 --- /dev/null +++ b/tests/expand/default/struct.expanded.rs @@ -0,0 +1,104 @@ +use pin_project::pin_project; +#[pin(__private())] +struct Struct { + #[pin] + pinned: T, + unpinned: U, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __StructProjection<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + } + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __StructProjectionRef<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + } + impl Struct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __StructProjection<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + __StructProjection { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + __StructProjectionRef { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl StructMustNotImplDrop for T {} + impl StructMustNotImplDrop for Struct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Struct { + 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 { + #[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..1c5e3b0 --- /dev/null +++ b/tests/expand/default/tuple_struct.expanded.rs @@ -0,0 +1,98 @@ +use pin_project::pin_project; +#[pin(__private())] +struct TupleStruct(#[pin] T, U); +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __TupleStructProjection<'pin, T, U>( + ::pin_project::__private::Pin<&'pin mut (T)>, + &'pin mut (U), + ) + where + TupleStruct: 'pin; + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __TupleStructProjectionRef<'pin, T, U>( + ::pin_project::__private::Pin<&'pin (T)>, + &'pin (U), + ) + where + TupleStruct: 'pin; + impl TupleStruct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __TupleStructProjection<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_unchecked_mut(); + __TupleStructProjection( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __TupleStructProjectionRef<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_ref(); + __TupleStructProjectionRef( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &TupleStruct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait TupleStructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl TupleStructMustNotImplDrop for T {} + impl TupleStructMustNotImplDrop for TupleStruct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for TupleStruct { + 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(#[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..8223de3 --- /dev/null +++ b/tests/expand/multifields/enum.expanded.rs @@ -0,0 +1,268 @@ +use pin_project::pin_project; +#[pin( + __private( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn + ) +)] +enum Enum { + Struct { #[pin] pinned1: T, #[pin] pinned2: T, unpinned1: U, unpinned2: U }, + Tuple(#[pin] T, #[pin] T, U, U), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::mut_mut)] +enum EnumProj<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned1: ::pin_project::__private::Pin<&'pin mut (T)>, + pinned2: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned1: &'pin mut (U), + unpinned2: &'pin mut (U), + }, + Tuple( + ::pin_project::__private::Pin<&'pin mut (T)>, + ::pin_project::__private::Pin<&'pin mut (T)>, + &'pin mut (U), + &'pin mut (U), + ), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::ref_option_ref)] +enum EnumProjRef<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned1: ::pin_project::__private::Pin<&'pin (T)>, + pinned2: ::pin_project::__private::Pin<&'pin (T)>, + unpinned1: &'pin (U), + unpinned2: &'pin (U), + }, + Tuple( + ::pin_project::__private::Pin<&'pin (T)>, + ::pin_project::__private::Pin<&'pin (T)>, + &'pin (U), + &'pin (U), + ), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(variant_size_differences)] +#[allow(clippy::large_enum_variant)] +enum EnumProjOwn { + Struct { + pinned1: ::pin_project::__private::PhantomData, + pinned2: ::pin_project::__private::PhantomData, + unpinned1: U, + unpinned2: U, + }, + Tuple( + ::pin_project::__private::PhantomData, + ::pin_project::__private::PhantomData, + U, + U, + ), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + impl Enum { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> EnumProj<'pin, T, U> { + unsafe { + match self.get_unchecked_mut() { + Self::Struct { pinned1, pinned2, unpinned1, unpinned2 } => { + EnumProj::Struct { + pinned1: _pin_project::__private::Pin::new_unchecked( + pinned1, + ), + pinned2: _pin_project::__private::Pin::new_unchecked( + pinned2, + ), + unpinned1, + unpinned2, + } + } + Self::Tuple(_0, _1, _2, _3) => { + EnumProj::Tuple( + _pin_project::__private::Pin::new_unchecked(_0), + _pin_project::__private::Pin::new_unchecked(_1), + _2, + _3, + ) + } + Self::Unit => EnumProj::Unit, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> EnumProjRef<'pin, T, U> { + unsafe { + match self.get_ref() { + Self::Struct { pinned1, pinned2, unpinned1, unpinned2 } => { + EnumProjRef::Struct { + pinned1: _pin_project::__private::Pin::new_unchecked( + pinned1, + ), + pinned2: _pin_project::__private::Pin::new_unchecked( + pinned2, + ), + unpinned1, + unpinned2, + } + } + Self::Tuple(_0, _1, _2, _3) => { + EnumProjRef::Tuple( + _pin_project::__private::Pin::new_unchecked(_0), + _pin_project::__private::Pin::new_unchecked(_1), + _2, + _3, + ) + } + Self::Unit => EnumProjRef::Unit, + } + } + } + #[allow(dead_code)] + fn project_replace( + self: _pin_project::__private::Pin<&mut Self>, + __replacement: Self, + ) -> EnumProjOwn { + unsafe { + let __self_ptr: *mut Self = self.get_unchecked_mut(); + let __guard = _pin_project::__private::UnsafeOverwriteGuard::new( + __self_ptr, + __replacement, + ); + match &mut *__self_ptr { + Self::Struct { pinned1, pinned2, unpinned1, unpinned2 } => { + let __result = EnumProjOwn::Struct { + pinned1: _pin_project::__private::PhantomData, + pinned2: _pin_project::__private::PhantomData, + unpinned1: _pin_project::__private::ptr::read(unpinned1), + unpinned2: _pin_project::__private::ptr::read(unpinned2), + }; + { + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + pinned2, + ); + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + pinned1, + ); + } + __result + } + Self::Tuple(_0, _1, _2, _3) => { + let __result = EnumProjOwn::Tuple( + _pin_project::__private::PhantomData, + _pin_project::__private::PhantomData, + _pin_project::__private::ptr::read(_2), + _pin_project::__private::ptr::read(_3), + ); + { + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + _1, + ); + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + _0, + ); + } + __result + } + Self::Unit => { + let __result = EnumProjOwn::Unit; + {} + __result + } + } + } + } + } + #[allow(missing_debug_implementations)] + struct __Enum<'pin, T, U> { + __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< + 'pin, + ( + _pin_project::__private::PhantomData, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + __field1: T, + __field2: T, + __field3: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait EnumMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl EnumMustNotImplDrop for T {} + impl EnumMustNotImplDrop for Enum {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Enum { + 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 { + 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..df8dc92 --- /dev/null +++ b/tests/expand/multifields/struct.expanded.rs @@ -0,0 +1,155 @@ +use pin_project::pin_project; +#[pin(__private(project_replace))] +struct Struct { + #[pin] + pinned1: T, + #[pin] + pinned2: T, + unpinned1: U, + unpinned2: U, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __StructProjection<'pin, T, U> + where + Struct: 'pin, + { + pinned1: ::pin_project::__private::Pin<&'pin mut (T)>, + pinned2: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned1: &'pin mut (U), + unpinned2: &'pin mut (U), + } + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __StructProjectionRef<'pin, T, U> + where + Struct: 'pin, + { + pinned1: ::pin_project::__private::Pin<&'pin (T)>, + pinned2: ::pin_project::__private::Pin<&'pin (T)>, + unpinned1: &'pin (U), + unpinned2: &'pin (U), + } + #[allow(dead_code)] + struct __StructProjectionOwned { + pinned1: ::pin_project::__private::PhantomData, + pinned2: ::pin_project::__private::PhantomData, + unpinned1: U, + unpinned2: U, + } + impl Struct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __StructProjection<'pin, T, U> { + unsafe { + let Self { pinned1, pinned2, unpinned1, unpinned2 } = self + .get_unchecked_mut(); + __StructProjection { + pinned1: _pin_project::__private::Pin::new_unchecked(pinned1), + pinned2: _pin_project::__private::Pin::new_unchecked(pinned2), + unpinned1, + unpinned2, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, T, U> { + unsafe { + let Self { pinned1, pinned2, unpinned1, unpinned2 } = self.get_ref(); + __StructProjectionRef { + pinned1: _pin_project::__private::Pin::new_unchecked(pinned1), + pinned2: _pin_project::__private::Pin::new_unchecked(pinned2), + unpinned1, + unpinned2, + } + } + } + #[allow(dead_code)] + fn project_replace( + self: _pin_project::__private::Pin<&mut Self>, + __replacement: Self, + ) -> __StructProjectionOwned { + unsafe { + let __self_ptr: *mut Self = self.get_unchecked_mut(); + let __guard = _pin_project::__private::UnsafeOverwriteGuard::new( + __self_ptr, + __replacement, + ); + let Self { pinned1, pinned2, unpinned1, unpinned2 } = &mut *__self_ptr; + let __result = __StructProjectionOwned { + pinned1: _pin_project::__private::PhantomData, + pinned2: _pin_project::__private::PhantomData, + unpinned1: _pin_project::__private::ptr::read(unpinned1), + unpinned2: _pin_project::__private::ptr::read(unpinned2), + }; + { + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + pinned2, + ); + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + pinned1, + ); + } + __result + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + __field1: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl StructMustNotImplDrop for T {} + impl StructMustNotImplDrop for Struct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Struct { + 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 { + #[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..0c85f9a --- /dev/null +++ b/tests/expand/multifields/tuple_struct.expanded.rs @@ -0,0 +1,145 @@ +use pin_project::pin_project; +#[pin(__private(project_replace))] +struct TupleStruct(#[pin] T, #[pin] T, U, U); +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __TupleStructProjection<'pin, T, U>( + ::pin_project::__private::Pin<&'pin mut (T)>, + ::pin_project::__private::Pin<&'pin mut (T)>, + &'pin mut (U), + &'pin mut (U), + ) + where + TupleStruct: 'pin; + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __TupleStructProjectionRef<'pin, T, U>( + ::pin_project::__private::Pin<&'pin (T)>, + ::pin_project::__private::Pin<&'pin (T)>, + &'pin (U), + &'pin (U), + ) + where + TupleStruct: 'pin; + #[allow(dead_code)] + struct __TupleStructProjectionOwned( + ::pin_project::__private::PhantomData, + ::pin_project::__private::PhantomData, + U, + U, + ); + impl TupleStruct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __TupleStructProjection<'pin, T, U> { + unsafe { + let Self(_0, _1, _2, _3) = self.get_unchecked_mut(); + __TupleStructProjection( + _pin_project::__private::Pin::new_unchecked(_0), + _pin_project::__private::Pin::new_unchecked(_1), + _2, + _3, + ) + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __TupleStructProjectionRef<'pin, T, U> { + unsafe { + let Self(_0, _1, _2, _3) = self.get_ref(); + __TupleStructProjectionRef( + _pin_project::__private::Pin::new_unchecked(_0), + _pin_project::__private::Pin::new_unchecked(_1), + _2, + _3, + ) + } + } + #[allow(dead_code)] + fn project_replace( + self: _pin_project::__private::Pin<&mut Self>, + __replacement: Self, + ) -> __TupleStructProjectionOwned { + unsafe { + let __self_ptr: *mut Self = self.get_unchecked_mut(); + let __guard = _pin_project::__private::UnsafeOverwriteGuard::new( + __self_ptr, + __replacement, + ); + let Self(_0, _1, _2, _3) = &mut *__self_ptr; + let __result = __TupleStructProjectionOwned( + _pin_project::__private::PhantomData, + _pin_project::__private::PhantomData, + _pin_project::__private::ptr::read(_2), + _pin_project::__private::ptr::read(_3), + ); + { + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + _1, + ); + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + _0, + ); + } + __result + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &TupleStruct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + __field1: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait TupleStructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl TupleStructMustNotImplDrop for T {} + impl TupleStructMustNotImplDrop for TupleStruct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for TupleStruct { + 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(#[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..8dbe768 --- /dev/null +++ b/tests/expand/naming/enum-all.expanded.rs @@ -0,0 +1,204 @@ +use pin_project::pin_project; +#[pin(__private(project = Proj, project_ref = ProjRef, project_replace = ProjOwn))] +enum Enum { + Struct { #[pin] pinned: T, unpinned: U }, + Tuple(#[pin] T, U), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::mut_mut)] +enum Proj<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + }, + Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::ref_option_ref)] +enum ProjRef<'pin, T, U> +where + Enum: 'pin, +{ + Struct { pinned: ::pin_project::__private::Pin<&'pin (T)>, unpinned: &'pin (U) }, + Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(variant_size_differences)] +#[allow(clippy::large_enum_variant)] +enum ProjOwn { + Struct { pinned: ::pin_project::__private::PhantomData, unpinned: U }, + Tuple(::pin_project::__private::PhantomData, U), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + impl Enum { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> Proj<'pin, T, U> { + unsafe { + match self.get_unchecked_mut() { + Self::Struct { pinned, unpinned } => { + Proj::Struct { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + Self::Tuple(_0, _1) => { + Proj::Tuple(_pin_project::__private::Pin::new_unchecked(_0), _1) + } + Self::Unit => Proj::Unit, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> ProjRef<'pin, T, U> { + unsafe { + match self.get_ref() { + Self::Struct { pinned, unpinned } => { + ProjRef::Struct { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + Self::Tuple(_0, _1) => { + ProjRef::Tuple( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + Self::Unit => ProjRef::Unit, + } + } + } + #[allow(dead_code)] + fn project_replace( + self: _pin_project::__private::Pin<&mut Self>, + __replacement: Self, + ) -> ProjOwn { + unsafe { + let __self_ptr: *mut Self = self.get_unchecked_mut(); + let __guard = _pin_project::__private::UnsafeOverwriteGuard::new( + __self_ptr, + __replacement, + ); + match &mut *__self_ptr { + Self::Struct { pinned, unpinned } => { + let __result = ProjOwn::Struct { + pinned: _pin_project::__private::PhantomData, + unpinned: _pin_project::__private::ptr::read(unpinned), + }; + { + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + pinned, + ); + } + __result + } + Self::Tuple(_0, _1) => { + let __result = ProjOwn::Tuple( + _pin_project::__private::PhantomData, + _pin_project::__private::ptr::read(_1), + ); + { + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + _0, + ); + } + __result + } + Self::Unit => { + let __result = ProjOwn::Unit; + {} + __result + } + } + } + } + } + #[allow(missing_debug_implementations)] + struct __Enum<'pin, T, U> { + __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< + 'pin, + ( + _pin_project::__private::PhantomData, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + __field1: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait EnumMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl EnumMustNotImplDrop for T {} + impl EnumMustNotImplDrop for Enum {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Enum { + 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 { + 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..c6916ec --- /dev/null +++ b/tests/expand/naming/enum-mut.expanded.rs @@ -0,0 +1,99 @@ +use pin_project::pin_project; +#[pin(__private(project = Proj))] +enum Enum { + Struct { #[pin] pinned: T, unpinned: U }, + Tuple(#[pin] T, U), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::mut_mut)] +enum Proj<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + }, + Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + impl Enum { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> Proj<'pin, T, U> { + unsafe { + match self.get_unchecked_mut() { + Self::Struct { pinned, unpinned } => { + Proj::Struct { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + Self::Tuple(_0, _1) => { + Proj::Tuple(_pin_project::__private::Pin::new_unchecked(_0), _1) + } + Self::Unit => Proj::Unit, + } + } + } + } + #[allow(missing_debug_implementations)] + struct __Enum<'pin, T, U> { + __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< + 'pin, + ( + _pin_project::__private::PhantomData, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + __field1: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait EnumMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl EnumMustNotImplDrop for T {} + impl EnumMustNotImplDrop for Enum {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Enum { + 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 { + 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..46477d1 --- /dev/null +++ b/tests/expand/naming/enum-none.expanded.rs @@ -0,0 +1,56 @@ +use pin_project::pin_project; +#[pin(__private())] +enum Enum { + Struct { #[pin] pinned: T, unpinned: U }, + Tuple(#[pin] T, U), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + impl Enum {} + #[allow(missing_debug_implementations)] + struct __Enum<'pin, T, U> { + __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< + 'pin, + ( + _pin_project::__private::PhantomData, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + __field1: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait EnumMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl EnumMustNotImplDrop for T {} + impl EnumMustNotImplDrop for Enum {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Enum { + 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 { + 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..ddeb00c --- /dev/null +++ b/tests/expand/naming/enum-own.expanded.rs @@ -0,0 +1,119 @@ +use pin_project::pin_project; +#[pin(__private(project_replace = ProjOwn))] +enum Enum { + Struct { #[pin] pinned: T, unpinned: U }, + Tuple(#[pin] T, U), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(variant_size_differences)] +#[allow(clippy::large_enum_variant)] +enum ProjOwn { + Struct { pinned: ::pin_project::__private::PhantomData, unpinned: U }, + Tuple(::pin_project::__private::PhantomData, U), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + impl Enum { + #[allow(dead_code)] + fn project_replace( + self: _pin_project::__private::Pin<&mut Self>, + __replacement: Self, + ) -> ProjOwn { + unsafe { + let __self_ptr: *mut Self = self.get_unchecked_mut(); + let __guard = _pin_project::__private::UnsafeOverwriteGuard::new( + __self_ptr, + __replacement, + ); + match &mut *__self_ptr { + Self::Struct { pinned, unpinned } => { + let __result = ProjOwn::Struct { + pinned: _pin_project::__private::PhantomData, + unpinned: _pin_project::__private::ptr::read(unpinned), + }; + { + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + pinned, + ); + } + __result + } + Self::Tuple(_0, _1) => { + let __result = ProjOwn::Tuple( + _pin_project::__private::PhantomData, + _pin_project::__private::ptr::read(_1), + ); + { + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + _0, + ); + } + __result + } + Self::Unit => { + let __result = ProjOwn::Unit; + {} + __result + } + } + } + } + } + #[allow(missing_debug_implementations)] + struct __Enum<'pin, T, U> { + __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< + 'pin, + ( + _pin_project::__private::PhantomData, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + __field1: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait EnumMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl EnumMustNotImplDrop for T {} + impl EnumMustNotImplDrop for Enum {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Enum { + 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 { + 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..1a49584 --- /dev/null +++ b/tests/expand/naming/enum-ref.expanded.rs @@ -0,0 +1,100 @@ +use pin_project::pin_project; +#[pin(__private(project_ref = ProjRef))] +enum Enum { + Struct { #[pin] pinned: T, unpinned: U }, + Tuple(#[pin] T, U), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::ref_option_ref)] +enum ProjRef<'pin, T, U> +where + Enum: 'pin, +{ + Struct { pinned: ::pin_project::__private::Pin<&'pin (T)>, unpinned: &'pin (U) }, + Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + impl Enum { + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> ProjRef<'pin, T, U> { + unsafe { + match self.get_ref() { + Self::Struct { pinned, unpinned } => { + ProjRef::Struct { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + Self::Tuple(_0, _1) => { + ProjRef::Tuple( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + Self::Unit => ProjRef::Unit, + } + } + } + } + #[allow(missing_debug_implementations)] + struct __Enum<'pin, T, U> { + __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< + 'pin, + ( + _pin_project::__private::PhantomData, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + __field1: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait EnumMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl EnumMustNotImplDrop for T {} + impl EnumMustNotImplDrop for Enum {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Enum { + 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 { + 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..e598a4f --- /dev/null +++ b/tests/expand/naming/struct-all.expanded.rs @@ -0,0 +1,163 @@ +use pin_project::pin_project; +#[pin(__private(project = Proj, project_ref = ProjRef, project_replace = ProjOwn))] +struct Struct { + #[pin] + pinned: T, + unpinned: U, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::mut_mut)] +struct Proj<'pin, T, U> +where + Struct: 'pin, +{ + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::ref_option_ref)] +struct ProjRef<'pin, T, U> +where + Struct: 'pin, +{ + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +struct ProjOwn { + pinned: ::pin_project::__private::PhantomData, + unpinned: U, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + impl Struct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> Proj<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + Proj { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> ProjRef<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + ProjRef { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + #[allow(dead_code)] + fn project_replace( + self: _pin_project::__private::Pin<&mut Self>, + __replacement: Self, + ) -> ProjOwn { + unsafe { + let __self_ptr: *mut Self = self.get_unchecked_mut(); + let __guard = _pin_project::__private::UnsafeOverwriteGuard::new( + __self_ptr, + __replacement, + ); + let Self { pinned, unpinned } = &mut *__self_ptr; + let __result = ProjOwn { + pinned: _pin_project::__private::PhantomData, + unpinned: _pin_project::__private::ptr::read(unpinned), + }; + { + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + pinned, + ); + } + __result + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl StructMustNotImplDrop for T {} + impl StructMustNotImplDrop for Struct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Struct { + 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 { + #[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..88782ee --- /dev/null +++ b/tests/expand/naming/struct-mut.expanded.rs @@ -0,0 +1,114 @@ +use pin_project::pin_project; +#[pin(__private(project = Proj))] +struct Struct { + #[pin] + pinned: T, + unpinned: U, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::mut_mut)] +struct Proj<'pin, T, U> +where + Struct: 'pin, +{ + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __StructProjectionRef<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + } + impl Struct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> Proj<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + Proj { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + __StructProjectionRef { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl StructMustNotImplDrop for T {} + impl StructMustNotImplDrop for Struct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Struct { + 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 { + #[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..0005d86 --- /dev/null +++ b/tests/expand/naming/struct-none.expanded.rs @@ -0,0 +1,104 @@ +use pin_project::pin_project; +#[pin(__private())] +struct Struct { + #[pin] + pinned: T, + unpinned: U, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __StructProjection<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + } + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __StructProjectionRef<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + } + impl Struct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __StructProjection<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + __StructProjection { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + __StructProjectionRef { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl StructMustNotImplDrop for T {} + impl StructMustNotImplDrop for Struct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Struct { + 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 { + #[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..cc24862 --- /dev/null +++ b/tests/expand/naming/struct-own.expanded.rs @@ -0,0 +1,143 @@ +use pin_project::pin_project; +#[pin(__private(project_replace = ProjOwn))] +struct Struct { + #[pin] + pinned: T, + unpinned: U, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +struct ProjOwn { + pinned: ::pin_project::__private::PhantomData, + unpinned: U, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __StructProjection<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + } + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __StructProjectionRef<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + } + impl Struct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __StructProjection<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + __StructProjection { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + __StructProjectionRef { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + #[allow(dead_code)] + fn project_replace( + self: _pin_project::__private::Pin<&mut Self>, + __replacement: Self, + ) -> ProjOwn { + unsafe { + let __self_ptr: *mut Self = self.get_unchecked_mut(); + let __guard = _pin_project::__private::UnsafeOverwriteGuard::new( + __self_ptr, + __replacement, + ); + let Self { pinned, unpinned } = &mut *__self_ptr; + let __result = ProjOwn { + pinned: _pin_project::__private::PhantomData, + unpinned: _pin_project::__private::ptr::read(unpinned), + }; + { + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + pinned, + ); + } + __result + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl StructMustNotImplDrop for T {} + impl StructMustNotImplDrop for Struct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Struct { + 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 { + #[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..e392f6f --- /dev/null +++ b/tests/expand/naming/struct-ref.expanded.rs @@ -0,0 +1,114 @@ +use pin_project::pin_project; +#[pin(__private(project_ref = ProjRef))] +struct Struct { + #[pin] + pinned: T, + unpinned: U, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::ref_option_ref)] +struct ProjRef<'pin, T, U> +where + Struct: 'pin, +{ + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __StructProjection<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + } + impl Struct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __StructProjection<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + __StructProjection { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> ProjRef<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + ProjRef { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl StructMustNotImplDrop for T {} + impl StructMustNotImplDrop for Struct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Struct { + 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 { + #[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..8c148ed --- /dev/null +++ b/tests/expand/naming/tuple_struct-all.expanded.rs @@ -0,0 +1,148 @@ +use pin_project::pin_project; +#[pin(__private(project = Proj, project_ref = ProjRef, project_replace = ProjOwn))] +struct TupleStruct(#[pin] T, U); +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::mut_mut)] +struct Proj<'pin, T, U>( + ::pin_project::__private::Pin<&'pin mut (T)>, + &'pin mut (U), +) +where + TupleStruct: 'pin; +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::ref_option_ref)] +struct ProjRef<'pin, T, U>( + ::pin_project::__private::Pin<&'pin (T)>, + &'pin (U), +) +where + TupleStruct: 'pin; +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +struct ProjOwn(::pin_project::__private::PhantomData, U); +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + impl TupleStruct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> Proj<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_unchecked_mut(); + Proj(_pin_project::__private::Pin::new_unchecked(_0), _1) + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> ProjRef<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_ref(); + ProjRef(_pin_project::__private::Pin::new_unchecked(_0), _1) + } + } + #[allow(dead_code)] + fn project_replace( + self: _pin_project::__private::Pin<&mut Self>, + __replacement: Self, + ) -> ProjOwn { + unsafe { + let __self_ptr: *mut Self = self.get_unchecked_mut(); + let __guard = _pin_project::__private::UnsafeOverwriteGuard::new( + __self_ptr, + __replacement, + ); + let Self(_0, _1) = &mut *__self_ptr; + let __result = ProjOwn( + _pin_project::__private::PhantomData, + _pin_project::__private::ptr::read(_1), + ); + { + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + _0, + ); + } + __result + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &TupleStruct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait TupleStructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl TupleStructMustNotImplDrop for T {} + impl TupleStructMustNotImplDrop for TupleStruct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for TupleStruct { + 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(#[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..79c7901 --- /dev/null +++ b/tests/expand/naming/tuple_struct-mut.expanded.rs @@ -0,0 +1,105 @@ +use pin_project::pin_project; +#[pin(__private(project = Proj))] +struct TupleStruct(#[pin] T, U); +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::mut_mut)] +struct Proj<'pin, T, U>( + ::pin_project::__private::Pin<&'pin mut (T)>, + &'pin mut (U), +) +where + TupleStruct: 'pin; +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __TupleStructProjectionRef<'pin, T, U>( + ::pin_project::__private::Pin<&'pin (T)>, + &'pin (U), + ) + where + TupleStruct: 'pin; + impl TupleStruct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> Proj<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_unchecked_mut(); + Proj(_pin_project::__private::Pin::new_unchecked(_0), _1) + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __TupleStructProjectionRef<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_ref(); + __TupleStructProjectionRef( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &TupleStruct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait TupleStructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl TupleStructMustNotImplDrop for T {} + impl TupleStructMustNotImplDrop for TupleStruct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for TupleStruct { + 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(#[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..1c5e3b0 --- /dev/null +++ b/tests/expand/naming/tuple_struct-none.expanded.rs @@ -0,0 +1,98 @@ +use pin_project::pin_project; +#[pin(__private())] +struct TupleStruct(#[pin] T, U); +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __TupleStructProjection<'pin, T, U>( + ::pin_project::__private::Pin<&'pin mut (T)>, + &'pin mut (U), + ) + where + TupleStruct: 'pin; + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __TupleStructProjectionRef<'pin, T, U>( + ::pin_project::__private::Pin<&'pin (T)>, + &'pin (U), + ) + where + TupleStruct: 'pin; + impl TupleStruct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __TupleStructProjection<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_unchecked_mut(); + __TupleStructProjection( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __TupleStructProjectionRef<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_ref(); + __TupleStructProjectionRef( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &TupleStruct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait TupleStructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl TupleStructMustNotImplDrop for T {} + impl TupleStructMustNotImplDrop for TupleStruct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for TupleStruct { + 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(#[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..37e4c34 --- /dev/null +++ b/tests/expand/naming/tuple_struct-own.expanded.rs @@ -0,0 +1,134 @@ +use pin_project::pin_project; +#[pin(__private(project_replace = ProjOwn))] +struct TupleStruct(#[pin] T, U); +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +struct ProjOwn(::pin_project::__private::PhantomData, U); +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __TupleStructProjection<'pin, T, U>( + ::pin_project::__private::Pin<&'pin mut (T)>, + &'pin mut (U), + ) + where + TupleStruct: 'pin; + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __TupleStructProjectionRef<'pin, T, U>( + ::pin_project::__private::Pin<&'pin (T)>, + &'pin (U), + ) + where + TupleStruct: 'pin; + impl TupleStruct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __TupleStructProjection<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_unchecked_mut(); + __TupleStructProjection( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __TupleStructProjectionRef<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_ref(); + __TupleStructProjectionRef( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + #[allow(dead_code)] + fn project_replace( + self: _pin_project::__private::Pin<&mut Self>, + __replacement: Self, + ) -> ProjOwn { + unsafe { + let __self_ptr: *mut Self = self.get_unchecked_mut(); + let __guard = _pin_project::__private::UnsafeOverwriteGuard::new( + __self_ptr, + __replacement, + ); + let Self(_0, _1) = &mut *__self_ptr; + let __result = ProjOwn( + _pin_project::__private::PhantomData, + _pin_project::__private::ptr::read(_1), + ); + { + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + _0, + ); + } + __result + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &TupleStruct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait TupleStructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl TupleStructMustNotImplDrop for T {} + impl TupleStructMustNotImplDrop for TupleStruct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for TupleStruct { + 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(#[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..8c86868 --- /dev/null +++ b/tests/expand/naming/tuple_struct-ref.expanded.rs @@ -0,0 +1,105 @@ +use pin_project::pin_project; +#[pin(__private(project_ref = ProjRef))] +struct TupleStruct(#[pin] T, U); +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::ref_option_ref)] +struct ProjRef<'pin, T, U>( + ::pin_project::__private::Pin<&'pin (T)>, + &'pin (U), +) +where + TupleStruct: 'pin; +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __TupleStructProjection<'pin, T, U>( + ::pin_project::__private::Pin<&'pin mut (T)>, + &'pin mut (U), + ) + where + TupleStruct: 'pin; + impl TupleStruct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __TupleStructProjection<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_unchecked_mut(); + __TupleStructProjection( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> ProjRef<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_ref(); + ProjRef(_pin_project::__private::Pin::new_unchecked(_0), _1) + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &TupleStruct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait TupleStructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl TupleStructMustNotImplDrop for T {} + impl TupleStructMustNotImplDrop for TupleStruct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for TupleStruct { + 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(#[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..98e7bbe --- /dev/null +++ b/tests/expand/not_unpin/enum.expanded.rs @@ -0,0 +1,139 @@ +use pin_project::pin_project; +#[pin(__private(!Unpin, project = EnumProj, project_ref = EnumProjRef))] +enum Enum { + Struct { #[pin] pinned: T, unpinned: U }, + Tuple(#[pin] T, U), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::mut_mut)] +enum EnumProj<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + }, + Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::ref_option_ref)] +enum EnumProjRef<'pin, T, U> +where + Enum: 'pin, +{ + Struct { pinned: ::pin_project::__private::Pin<&'pin (T)>, unpinned: &'pin (U) }, + Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + impl Enum { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> EnumProj<'pin, T, U> { + unsafe { + match self.get_unchecked_mut() { + Self::Struct { pinned, unpinned } => { + EnumProj::Struct { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + Self::Tuple(_0, _1) => { + EnumProj::Tuple( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + Self::Unit => EnumProj::Unit, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> EnumProjRef<'pin, T, U> { + unsafe { + match self.get_ref() { + Self::Struct { pinned, unpinned } => { + EnumProjRef::Struct { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + Self::Tuple(_0, _1) => { + EnumProjRef::Tuple( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + Self::Unit => EnumProjRef::Unit, + } + } + } + } + impl<'pin, T, U> _pin_project::__private::Unpin for Enum + 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 + where + _pin_project::__private::Wrapper< + 'pin, + _pin_project::__private::PhantomPinned, + >: _pin_project::__private::Unpin, + {} + trait EnumMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl EnumMustNotImplDrop for T {} + impl EnumMustNotImplDrop for Enum {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Enum { + 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 { + 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..420f21a --- /dev/null +++ b/tests/expand/not_unpin/struct.expanded.rs @@ -0,0 +1,99 @@ +use pin_project::pin_project; +#[pin(__private(!Unpin))] +struct Struct { + #[pin] + pinned: T, + unpinned: U, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __StructProjection<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + } + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __StructProjectionRef<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + } + impl Struct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __StructProjection<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + __StructProjection { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + __StructProjectionRef { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + let _ = &this.pinned; + let _ = &this.unpinned; + } + impl<'pin, T, U> _pin_project::__private::Unpin for Struct + 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 + where + _pin_project::__private::Wrapper< + 'pin, + _pin_project::__private::PhantomPinned, + >: _pin_project::__private::Unpin, + {} + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl StructMustNotImplDrop for T {} + impl StructMustNotImplDrop for Struct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Struct { + 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 { + #[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..99621f4 --- /dev/null +++ b/tests/expand/not_unpin/tuple_struct.expanded.rs @@ -0,0 +1,93 @@ +use pin_project::pin_project; +#[pin(__private(!Unpin))] +struct TupleStruct(#[pin] T, U); +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __TupleStructProjection<'pin, T, U>( + ::pin_project::__private::Pin<&'pin mut (T)>, + &'pin mut (U), + ) + where + TupleStruct: 'pin; + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __TupleStructProjectionRef<'pin, T, U>( + ::pin_project::__private::Pin<&'pin (T)>, + &'pin (U), + ) + where + TupleStruct: 'pin; + impl TupleStruct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __TupleStructProjection<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_unchecked_mut(); + __TupleStructProjection( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __TupleStructProjectionRef<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_ref(); + __TupleStructProjectionRef( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &TupleStruct) { + let _ = &this.0; + let _ = &this.1; + } + impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct + 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 + where + _pin_project::__private::Wrapper< + 'pin, + _pin_project::__private::PhantomPinned, + >: _pin_project::__private::Unpin, + {} + trait TupleStructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl TupleStructMustNotImplDrop for T {} + impl TupleStructMustNotImplDrop for TupleStruct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for TupleStruct { + 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(#[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..1a8e746 --- /dev/null +++ b/tests/expand/pinned_drop/enum.expanded.rs @@ -0,0 +1,157 @@ +use std::pin::Pin; +use pin_project::{pin_project, pinned_drop}; +#[pin(__private(PinnedDrop, project = EnumProj, project_ref = EnumProjRef))] +enum Enum { + Struct { #[pin] pinned: T, unpinned: U }, + Tuple(#[pin] T, U), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::mut_mut)] +enum EnumProj<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + }, + Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::ref_option_ref)] +enum EnumProjRef<'pin, T, U> +where + Enum: 'pin, +{ + Struct { pinned: ::pin_project::__private::Pin<&'pin (T)>, unpinned: &'pin (U) }, + Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + impl Enum { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> EnumProj<'pin, T, U> { + unsafe { + match self.get_unchecked_mut() { + Self::Struct { pinned, unpinned } => { + EnumProj::Struct { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + Self::Tuple(_0, _1) => { + EnumProj::Tuple( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + Self::Unit => EnumProj::Unit, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> EnumProjRef<'pin, T, U> { + unsafe { + match self.get_ref() { + Self::Struct { pinned, unpinned } => { + EnumProjRef::Struct { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + Self::Tuple(_0, _1) => { + EnumProjRef::Tuple( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + Self::Unit => EnumProjRef::Unit, + } + } + } + } + #[allow(missing_debug_implementations)] + struct __Enum<'pin, T, U> { + __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< + 'pin, + ( + _pin_project::__private::PhantomData, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + __field1: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + impl _pin_project::__private::Drop for Enum { + fn drop(&mut self) { + unsafe { + let __pinned_self = _pin_project::__private::Pin::new_unchecked(self); + _pin_project::__private::PinnedDrop::drop(__pinned_self); + } + } + } +}; +#[doc(hidden)] +impl ::pin_project::__private::PinnedDrop for Enum { + unsafe fn drop(self: Pin<&mut Self>) { + #[allow(clippy::needless_pass_by_value)] + fn __drop_inner(__self: Pin<&mut Enum>) { + 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..c162ef6 --- /dev/null +++ b/tests/expand/pinned_drop/enum.rs @@ -0,0 +1,23 @@ +use std::pin::Pin; + +use pin_project::{pin_project, pinned_drop}; + +#[pin_project(PinnedDrop, project = EnumProj, project_ref = EnumProjRef)] +enum Enum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, +} + +#[pinned_drop] +impl PinnedDrop for Enum { + 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..d21440d --- /dev/null +++ b/tests/expand/pinned_drop/struct.expanded.rs @@ -0,0 +1,116 @@ +use std::pin::Pin; +use pin_project::{pin_project, pinned_drop}; +#[pin(__private(PinnedDrop))] +struct Struct { + #[pin] + pinned: T, + unpinned: U, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __StructProjection<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + } + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __StructProjectionRef<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + } + impl Struct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __StructProjection<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + __StructProjection { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + __StructProjectionRef { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + impl _pin_project::__private::Drop for Struct { + fn drop(&mut self) { + unsafe { + let __pinned_self = _pin_project::__private::Pin::new_unchecked(self); + _pin_project::__private::PinnedDrop::drop(__pinned_self); + } + } + } +}; +#[doc(hidden)] +impl ::pin_project::__private::PinnedDrop for Struct { + unsafe fn drop(self: Pin<&mut Self>) { + #[allow(clippy::needless_pass_by_value)] + fn __drop_inner(__self: Pin<&mut Struct>) { + 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..691d3cb --- /dev/null +++ b/tests/expand/pinned_drop/struct.rs @@ -0,0 +1,19 @@ +use std::pin::Pin; + +use pin_project::{pin_project, pinned_drop}; + +#[pin_project(PinnedDrop)] +struct Struct { + #[pin] + pinned: T, + unpinned: U, +} + +#[pinned_drop] +impl PinnedDrop for Struct { + 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..9a614ae --- /dev/null +++ b/tests/expand/pinned_drop/tuple_struct.expanded.rs @@ -0,0 +1,110 @@ +use std::pin::Pin; +use pin_project::{pin_project, pinned_drop}; +#[pin(__private(PinnedDrop))] +struct TupleStruct(#[pin] T, U); +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __TupleStructProjection<'pin, T, U>( + ::pin_project::__private::Pin<&'pin mut (T)>, + &'pin mut (U), + ) + where + TupleStruct: 'pin; + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __TupleStructProjectionRef<'pin, T, U>( + ::pin_project::__private::Pin<&'pin (T)>, + &'pin (U), + ) + where + TupleStruct: 'pin; + impl TupleStruct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __TupleStructProjection<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_unchecked_mut(); + __TupleStructProjection( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __TupleStructProjectionRef<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_ref(); + __TupleStructProjectionRef( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &TupleStruct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + impl _pin_project::__private::Drop for TupleStruct { + fn drop(&mut self) { + unsafe { + let __pinned_self = _pin_project::__private::Pin::new_unchecked(self); + _pin_project::__private::PinnedDrop::drop(__pinned_self); + } + } + } +}; +#[doc(hidden)] +impl ::pin_project::__private::PinnedDrop for TupleStruct { + unsafe fn drop(self: Pin<&mut Self>) { + #[allow(clippy::needless_pass_by_value)] + fn __drop_inner(__self: Pin<&mut TupleStruct>) { + 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..1f4917c --- /dev/null +++ b/tests/expand/pinned_drop/tuple_struct.rs @@ -0,0 +1,15 @@ +use std::pin::Pin; + +use pin_project::{pin_project, pinned_drop}; + +#[pin_project(PinnedDrop)] +struct TupleStruct(#[pin] T, U); + +#[pinned_drop] +impl PinnedDrop for TupleStruct { + 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..178cb99 --- /dev/null +++ b/tests/expand/project_replace/enum.expanded.rs @@ -0,0 +1,119 @@ +use pin_project::pin_project; +#[pin(__private(project_replace = EnumProjOwn))] +enum Enum { + Struct { #[pin] pinned: T, unpinned: U }, + Tuple(#[pin] T, U), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(variant_size_differences)] +#[allow(clippy::large_enum_variant)] +enum EnumProjOwn { + Struct { pinned: ::pin_project::__private::PhantomData, unpinned: U }, + Tuple(::pin_project::__private::PhantomData, U), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + impl Enum { + #[allow(dead_code)] + fn project_replace( + self: _pin_project::__private::Pin<&mut Self>, + __replacement: Self, + ) -> EnumProjOwn { + unsafe { + let __self_ptr: *mut Self = self.get_unchecked_mut(); + let __guard = _pin_project::__private::UnsafeOverwriteGuard::new( + __self_ptr, + __replacement, + ); + match &mut *__self_ptr { + Self::Struct { pinned, unpinned } => { + let __result = EnumProjOwn::Struct { + pinned: _pin_project::__private::PhantomData, + unpinned: _pin_project::__private::ptr::read(unpinned), + }; + { + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + pinned, + ); + } + __result + } + Self::Tuple(_0, _1) => { + let __result = EnumProjOwn::Tuple( + _pin_project::__private::PhantomData, + _pin_project::__private::ptr::read(_1), + ); + { + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + _0, + ); + } + __result + } + Self::Unit => { + let __result = EnumProjOwn::Unit; + {} + __result + } + } + } + } + } + #[allow(missing_debug_implementations)] + struct __Enum<'pin, T, U> { + __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< + 'pin, + ( + _pin_project::__private::PhantomData, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + __field1: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait EnumMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl EnumMustNotImplDrop for T {} + impl EnumMustNotImplDrop for Enum {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Enum { + 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 { + 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..45839a2 --- /dev/null +++ b/tests/expand/project_replace/struct.expanded.rs @@ -0,0 +1,133 @@ +use pin_project::pin_project; +#[pin(__private(project_replace))] +struct Struct { + #[pin] + pinned: T, + unpinned: U, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __StructProjection<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + } + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __StructProjectionRef<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + } + #[allow(dead_code)] + struct __StructProjectionOwned { + pinned: ::pin_project::__private::PhantomData, + unpinned: U, + } + impl Struct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __StructProjection<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + __StructProjection { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + __StructProjectionRef { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + #[allow(dead_code)] + fn project_replace( + self: _pin_project::__private::Pin<&mut Self>, + __replacement: Self, + ) -> __StructProjectionOwned { + unsafe { + let __self_ptr: *mut Self = self.get_unchecked_mut(); + let __guard = _pin_project::__private::UnsafeOverwriteGuard::new( + __self_ptr, + __replacement, + ); + let Self { pinned, unpinned } = &mut *__self_ptr; + let __result = __StructProjectionOwned { + pinned: _pin_project::__private::PhantomData, + unpinned: _pin_project::__private::ptr::read(unpinned), + }; + { + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + pinned, + ); + } + __result + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl StructMustNotImplDrop for T {} + impl StructMustNotImplDrop for Struct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Struct { + 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 { + #[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..cdee3d1 --- /dev/null +++ b/tests/expand/project_replace/tuple_struct.expanded.rs @@ -0,0 +1,127 @@ +use pin_project::pin_project; +#[pin(__private(project_replace))] +struct TupleStruct(#[pin] T, U); +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __TupleStructProjection<'pin, T, U>( + ::pin_project::__private::Pin<&'pin mut (T)>, + &'pin mut (U), + ) + where + TupleStruct: 'pin; + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __TupleStructProjectionRef<'pin, T, U>( + ::pin_project::__private::Pin<&'pin (T)>, + &'pin (U), + ) + where + TupleStruct: 'pin; + #[allow(dead_code)] + struct __TupleStructProjectionOwned( + ::pin_project::__private::PhantomData, + U, + ); + impl TupleStruct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __TupleStructProjection<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_unchecked_mut(); + __TupleStructProjection( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __TupleStructProjectionRef<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_ref(); + __TupleStructProjectionRef( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + #[allow(dead_code)] + fn project_replace( + self: _pin_project::__private::Pin<&mut Self>, + __replacement: Self, + ) -> __TupleStructProjectionOwned { + unsafe { + let __self_ptr: *mut Self = self.get_unchecked_mut(); + let __guard = _pin_project::__private::UnsafeOverwriteGuard::new( + __self_ptr, + __replacement, + ); + let Self(_0, _1) = &mut *__self_ptr; + let __result = __TupleStructProjectionOwned( + _pin_project::__private::PhantomData, + _pin_project::__private::ptr::read(_1), + ); + { + let __guard = _pin_project::__private::UnsafeDropInPlaceGuard::new( + _0, + ); + } + __result + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &TupleStruct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait TupleStructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl TupleStructMustNotImplDrop for T {} + impl TupleStructMustNotImplDrop for TupleStruct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for TupleStruct { + 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(#[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..90be268 --- /dev/null +++ b/tests/expand/pub/enum.expanded.rs @@ -0,0 +1,145 @@ +use pin_project::pin_project; +#[pin(__private(project = EnumProj, project_ref = EnumProjRef))] +pub enum Enum { + Struct { #[pin] pinned: T, unpinned: U }, + Tuple(#[pin] T, U), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::mut_mut)] +pub(crate) enum EnumProj<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + }, + Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::ref_option_ref)] +pub(crate) enum EnumProjRef<'pin, T, U> +where + Enum: 'pin, +{ + Struct { pinned: ::pin_project::__private::Pin<&'pin (T)>, unpinned: &'pin (U) }, + Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + impl Enum { + #[allow(dead_code)] + pub(crate) fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> EnumProj<'pin, T, U> { + unsafe { + match self.get_unchecked_mut() { + Self::Struct { pinned, unpinned } => { + EnumProj::Struct { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + Self::Tuple(_0, _1) => { + EnumProj::Tuple( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + Self::Unit => EnumProj::Unit, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + pub(crate) fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> EnumProjRef<'pin, T, U> { + unsafe { + match self.get_ref() { + Self::Struct { pinned, unpinned } => { + EnumProjRef::Struct { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + Self::Tuple(_0, _1) => { + EnumProjRef::Tuple( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + Self::Unit => EnumProjRef::Unit, + } + } + } + } + #[allow(missing_debug_implementations)] + pub struct __Enum<'pin, T, U> { + __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< + 'pin, + ( + _pin_project::__private::PhantomData, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + __field1: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum + where + __Enum<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait EnumMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl EnumMustNotImplDrop for T {} + impl EnumMustNotImplDrop for Enum {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Enum { + 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 { + 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..ca31f3d --- /dev/null +++ b/tests/expand/pub/struct.expanded.rs @@ -0,0 +1,104 @@ +use pin_project::pin_project; +#[pin(__private())] +pub struct Struct { + #[pin] + pub pinned: T, + pub unpinned: U, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + pub(crate) struct __StructProjection<'pin, T, U> + where + Struct: 'pin, + { + pub pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + pub unpinned: &'pin mut (U), + } + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + pub(crate) struct __StructProjectionRef<'pin, T, U> + where + Struct: 'pin, + { + pub pinned: ::pin_project::__private::Pin<&'pin (T)>, + pub unpinned: &'pin (U), + } + impl Struct { + #[allow(dead_code)] + pub(crate) fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __StructProjection<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + __StructProjection { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + pub(crate) fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + __StructProjectionRef { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct + where + __Struct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl StructMustNotImplDrop for T {} + impl StructMustNotImplDrop for Struct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Struct { + 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 { + #[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..5c7efbf --- /dev/null +++ b/tests/expand/pub/tuple_struct.expanded.rs @@ -0,0 +1,98 @@ +use pin_project::pin_project; +#[pin(__private())] +pub struct TupleStruct(#[pin] pub T, pub U); +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + pub(crate) struct __TupleStructProjection<'pin, T, U>( + pub ::pin_project::__private::Pin<&'pin mut (T)>, + pub &'pin mut (U), + ) + where + TupleStruct: 'pin; + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + pub(crate) struct __TupleStructProjectionRef<'pin, T, U>( + pub ::pin_project::__private::Pin<&'pin (T)>, + pub &'pin (U), + ) + where + TupleStruct: 'pin; + impl TupleStruct { + #[allow(dead_code)] + pub(crate) fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __TupleStructProjection<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_unchecked_mut(); + __TupleStructProjection( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + pub(crate) fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __TupleStructProjectionRef<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_ref(); + __TupleStructProjectionRef( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &TupleStruct) { + 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, + _pin_project::__private::PhantomData, + ), + >, + __field0: T, + } + impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + #[doc(hidden)] + unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct + where + __TupleStruct<'pin, T, U>: _pin_project::__private::Unpin, + {} + trait TupleStructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl TupleStructMustNotImplDrop for T {} + impl TupleStructMustNotImplDrop for TupleStruct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for TupleStruct { + 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(#[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..1f88ccc --- /dev/null +++ b/tests/expand/unsafe_unpin/enum.expanded.rs @@ -0,0 +1,129 @@ +use pin_project::{pin_project, UnsafeUnpin}; +#[pin(__private(UnsafeUnpin, project = EnumProj, project_ref = EnumProjRef))] +enum Enum { + Struct { #[pin] pinned: T, unpinned: U }, + Tuple(#[pin] T, U), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::mut_mut)] +enum EnumProj<'pin, T, U> +where + Enum: 'pin, +{ + Struct { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + }, + Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(dead_code)] +#[allow(clippy::ref_option_ref)] +enum EnumProjRef<'pin, T, U> +where + Enum: 'pin, +{ + Struct { pinned: ::pin_project::__private::Pin<&'pin (T)>, unpinned: &'pin (U) }, + Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), + Unit, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + impl Enum { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> EnumProj<'pin, T, U> { + unsafe { + match self.get_unchecked_mut() { + Self::Struct { pinned, unpinned } => { + EnumProj::Struct { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + Self::Tuple(_0, _1) => { + EnumProj::Tuple( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + Self::Unit => EnumProj::Unit, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> EnumProjRef<'pin, T, U> { + unsafe { + match self.get_ref() { + Self::Struct { pinned, unpinned } => { + EnumProjRef::Struct { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + Self::Tuple(_0, _1) => { + EnumProjRef::Tuple( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + Self::Unit => EnumProjRef::Unit, + } + } + } + } + impl<'pin, T, U> _pin_project::__private::Unpin for Enum + where + _pin_project::__private::Wrapper<'pin, Self>: _pin_project::UnsafeUnpin, + {} + trait EnumMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl EnumMustNotImplDrop for T {} + impl EnumMustNotImplDrop for Enum {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Enum { + unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} + } +}; +unsafe impl UnsafeUnpin for Enum {} +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 { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, +} + +unsafe impl UnsafeUnpin for Enum {} + +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..5fa7271 --- /dev/null +++ b/tests/expand/unsafe_unpin/struct.expanded.rs @@ -0,0 +1,89 @@ +use pin_project::{pin_project, UnsafeUnpin}; +#[pin(__private(UnsafeUnpin))] +struct Struct { + #[pin] + pinned: T, + unpinned: U, +} +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __StructProjection<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin mut (T)>, + unpinned: &'pin mut (U), + } + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __StructProjectionRef<'pin, T, U> + where + Struct: 'pin, + { + pinned: ::pin_project::__private::Pin<&'pin (T)>, + unpinned: &'pin (U), + } + impl Struct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __StructProjection<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_unchecked_mut(); + __StructProjection { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, T, U> { + unsafe { + let Self { pinned, unpinned } = self.get_ref(); + __StructProjectionRef { + pinned: _pin_project::__private::Pin::new_unchecked(pinned), + unpinned, + } + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &Struct) { + let _ = &this.pinned; + let _ = &this.unpinned; + } + impl<'pin, T, U> _pin_project::__private::Unpin for Struct + where + _pin_project::__private::Wrapper<'pin, Self>: _pin_project::UnsafeUnpin, + {} + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl StructMustNotImplDrop for T {} + impl StructMustNotImplDrop for Struct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for Struct { + unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} + } +}; +unsafe impl UnsafeUnpin for Struct {} +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 { + #[pin] + pinned: T, + unpinned: U, +} + +unsafe impl UnsafeUnpin for Struct {} + +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..de4e926 --- /dev/null +++ b/tests/expand/unsafe_unpin/tuple_struct.expanded.rs @@ -0,0 +1,83 @@ +use pin_project::{pin_project, UnsafeUnpin}; +#[pin(__private(UnsafeUnpin))] +struct TupleStruct(#[pin] T, U); +#[allow(box_pointers)] +#[allow(deprecated)] +#[allow(explicit_outlives_requirements)] +#[allow(single_use_lifetimes)] +#[allow(unreachable_pub)] +#[allow(unused_tuple_struct_fields)] +#[allow(clippy::unknown_clippy_lints)] +#[allow(clippy::pattern_type_mismatch)] +#[allow(clippy::redundant_pub_crate)] +#[allow(clippy::type_repetition_in_bounds)] +#[allow(unused_qualifications)] +#[allow(clippy::semicolon_if_nothing_returned)] +#[allow(clippy::use_self)] +#[allow(clippy::used_underscore_binding)] +const _: () = { + #[allow(unused_extern_crates)] + extern crate pin_project as _pin_project; + #[allow(dead_code)] + #[allow(clippy::mut_mut)] + struct __TupleStructProjection<'pin, T, U>( + ::pin_project::__private::Pin<&'pin mut (T)>, + &'pin mut (U), + ) + where + TupleStruct: 'pin; + #[allow(dead_code)] + #[allow(clippy::ref_option_ref)] + struct __TupleStructProjectionRef<'pin, T, U>( + ::pin_project::__private::Pin<&'pin (T)>, + &'pin (U), + ) + where + TupleStruct: 'pin; + impl TupleStruct { + #[allow(dead_code)] + fn project<'pin>( + self: _pin_project::__private::Pin<&'pin mut Self>, + ) -> __TupleStructProjection<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_unchecked_mut(); + __TupleStructProjection( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + #[allow(dead_code)] + #[allow(clippy::missing_const_for_fn)] + fn project_ref<'pin>( + self: _pin_project::__private::Pin<&'pin Self>, + ) -> __TupleStructProjectionRef<'pin, T, U> { + unsafe { + let Self(_0, _1) = self.get_ref(); + __TupleStructProjectionRef( + _pin_project::__private::Pin::new_unchecked(_0), + _1, + ) + } + } + } + #[forbid(unaligned_references, safe_packed_borrows)] + fn __assert_not_repr_packed(this: &TupleStruct) { + let _ = &this.0; + let _ = &this.1; + } + impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct + where + _pin_project::__private::Wrapper<'pin, Self>: _pin_project::UnsafeUnpin, + {} + trait TupleStructMustNotImplDrop {} + #[allow(clippy::drop_bounds, drop_bounds)] + impl TupleStructMustNotImplDrop for T {} + impl TupleStructMustNotImplDrop for TupleStruct {} + #[doc(hidden)] + impl _pin_project::__private::PinnedDrop for TupleStruct { + unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} + } +}; +unsafe impl UnsafeUnpin for Struct {} +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(#[pin] T, U); + +unsafe impl UnsafeUnpin for Struct {} + +fn main() {} diff --git a/tests/expandtest.rs b/tests/expandtest.rs new file mode 100644 index 0000000..4feec1a --- /dev/null +++ b/tests/expandtest.rs @@ -0,0 +1,43 @@ +#![cfg(not(miri))] +#![warn(rust_2018_idioms, single_use_lifetimes)] + +use std::{ + env, + process::{Command, ExitStatus, Stdio}, +}; + +const PATH: &str = "tests/expand/**/*.rs"; + +#[rustversion::attr(not(nightly), ignore)] +#[test] +fn expandtest() { + let is_ci = env::var_os("CI").is_some(); + let cargo = &*env::var("CARGO").unwrap_or_else(|_| "cargo".into()); + if !has_command(&[cargo, "expand"]) { + if is_ci { + panic!("expandtest requires cargo-expand"); + } + return; + } + + let args = &["--all-features"]; + if is_ci { + macrotest::expand_without_refresh_args(PATH, args); + } else { + env::set_var("MACROTEST", "overwrite"); + macrotest::expand_args(PATH, args); + } +} + +fn has_command(command: &[&str]) -> bool { + Command::new(command[0]) + .args(&command[1..]) + .arg("--version") + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status() + .as_ref() + .map(ExitStatus::success) + .unwrap_or(false) +} diff --git a/tests/include/basic-safe-part.rs b/tests/include/basic-safe-part.rs new file mode 100644 index 0000000..0b7c43e --- /dev/null +++ b/tests/include/basic-safe-part.rs @@ -0,0 +1,193 @@ +// default #[pin_project], PinnedDrop, project_replace, !Unpin, and UnsafeUnpin without UnsafeUnpin impl are completely safe. + +#[::pin_project::pin_project] +#[derive(Debug)] +pub struct DefaultStruct { + #[pin] + pub pinned: T, + pub unpinned: U, +} + +#[::pin_project::pin_project( + project = DefaultStructNamedProj, + project_ref = DefaultStructNamedProjRef, +)] +#[derive(Debug)] +pub struct DefaultStructNamed { + #[pin] + pub pinned: T, + pub unpinned: U, +} + +#[::pin_project::pin_project] +#[derive(Debug)] +pub struct DefaultTupleStruct(#[pin] pub T, pub U); + +#[::pin_project::pin_project( + project = DefaultTupleStructNamedProj, + project_ref = DefaultTupleStructNamedProjRef, +)] +#[derive(Debug)] +pub struct DefaultTupleStructNamed(#[pin] pub T, pub U); + +#[::pin_project::pin_project( + project = DefaultEnumProj, + project_ref = DefaultEnumProjRef, +)] +#[derive(Debug)] +pub enum DefaultEnum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, +} + +#[::pin_project::pin_project(PinnedDrop)] +#[derive(Debug)] +pub struct PinnedDropStruct { + #[pin] + pub pinned: T, + pub unpinned: U, +} + +#[::pin_project::pinned_drop] +impl PinnedDrop for PinnedDropStruct { + fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} +} + +#[::pin_project::pin_project(PinnedDrop)] +#[derive(Debug)] +pub struct PinnedDropTupleStruct(#[pin] pub T, pub U); + +#[::pin_project::pinned_drop] +impl PinnedDrop for PinnedDropTupleStruct { + fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} +} + +#[::pin_project::pin_project( + PinnedDrop, + project = PinnedDropEnumProj, + project_ref = PinnedDropEnumProjRef, +)] +#[derive(Debug)] +pub enum PinnedDropEnum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, +} + +#[::pin_project::pinned_drop] +impl PinnedDrop for PinnedDropEnum { + fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} +} + +#[::pin_project::pin_project(project_replace)] +#[derive(Debug)] +pub struct ReplaceStruct { + #[pin] + pub pinned: T, + pub unpinned: U, +} + +#[::pin_project::pin_project( + project = ReplaceStructNamedProj, + project_ref = ReplaceStructNamedProjRef, + project_replace = ReplaceStructNamedProjOwn, +)] +#[derive(Debug)] +pub struct ReplaceStructNamed { + #[pin] + pub pinned: T, + pub unpinned: U, +} + +#[::pin_project::pin_project(project_replace)] +#[derive(Debug)] +pub struct ReplaceTupleStruct(#[pin] pub T, pub U); + +#[::pin_project::pin_project( + project = ReplaceTupleStructNamedProj, + project_ref = ReplaceTupleStructNamedProjRef, + project_replace = ReplaceTupleStructNamedProjOwn, +)] +#[derive(Debug)] +pub struct ReplaceTupleStructNamed(#[pin] pub T, pub U); + +#[::pin_project::pin_project( + project = ReplaceEnumProj, + project_ref = ReplaceEnumProjRef, + project_replace = ReplaceEnumProjOwn, +)] +#[derive(Debug)] +pub enum ReplaceEnum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, +} + +#[::pin_project::pin_project(UnsafeUnpin)] +#[derive(Debug)] +pub struct UnsafeUnpinStruct { + #[pin] + pub pinned: T, + pub unpinned: U, +} + +#[::pin_project::pin_project(UnsafeUnpin)] +#[derive(Debug)] +pub struct UnsafeUnpinTupleStruct(#[pin] pub T, pub U); + +#[::pin_project::pin_project( + UnsafeUnpin, + project = UnsafeUnpinEnumProj, + project_ref = UnsafeUnpinEnumProjRef, +)] +#[derive(Debug)] +pub enum UnsafeUnpinEnum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, +} + +#[::pin_project::pin_project(!Unpin)] +#[derive(Debug)] +pub struct NotUnpinStruct { + #[pin] + pub pinned: T, + pub unpinned: U, +} + +#[::pin_project::pin_project(!Unpin)] +#[derive(Debug)] +pub struct NotUnpinTupleStruct(#[pin] pub T, pub U); + +#[::pin_project::pin_project( + !Unpin, + project = NotUnpinEnumProj, + project_ref = NotUnpinEnumProjRef, +)] +#[derive(Debug)] +pub enum NotUnpinEnum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, +} diff --git a/tests/include/basic.rs b/tests/include/basic.rs new file mode 100644 index 0000000..57cbaeb --- /dev/null +++ b/tests/include/basic.rs @@ -0,0 +1,17 @@ +include!("basic-safe-part.rs"); + +#[allow(clippy::undocumented_unsafe_blocks)] +unsafe impl + ::pin_project::UnsafeUnpin for UnsafeUnpinStruct +{ +} +#[allow(clippy::undocumented_unsafe_blocks)] +unsafe impl + ::pin_project::UnsafeUnpin for UnsafeUnpinTupleStruct +{ +} +#[allow(clippy::undocumented_unsafe_blocks)] +unsafe impl + ::pin_project::UnsafeUnpin for UnsafeUnpinEnum +{ +} diff --git a/tests/lint.rs b/tests/lint.rs new file mode 100644 index 0000000..35f05d5 --- /dev/null +++ b/tests/lint.rs @@ -0,0 +1,1190 @@ +// Check interoperability with rustc and clippy lints. + +// for old compilers +#![allow(unknown_lints)] +#![warn(nonstandard_style, rust_2018_idioms, unused)] +// Note: This does not guarantee compatibility with forbidding these lints in the future. +// If rustc adds a new lint, we may not be able to keep this. +#![forbid(future_incompatible, rust_2018_compatibility, rust_2021_compatibility)] +// lints forbidden as a part of future_incompatible, rust_2018_compatibility, and rust_2021_compatibility are not included in the list below. +// elided_lifetimes_in_paths, explicit_outlives_requirements, unused_extern_crates: as a part of rust_2018_idioms +// unsafe_op_in_unsafe_fn: requires Rust 1.52. and, we don't generate unsafe fn. +// non_exhaustive_omitted_patterns: unstable +// unstable_features: no way to generate #![feature(..)] by macros, expect for unstable inner attribute. and this lint is deprecated: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unstable-features +// unused_crate_dependencies, must_not_suspend: unrelated +// unsafe_code: checked in forbid_unsafe module +#![warn( + box_pointers, + deprecated_in_future, + fuzzy_provenance_casts, + lossy_provenance_casts, + macro_use_extern_crate, + meta_variable_misuse, + missing_abi, + missing_copy_implementations, + missing_debug_implementations, + missing_docs, + non_ascii_idents, + noop_method_call, + single_use_lifetimes, + trivial_casts, + trivial_numeric_casts, + unreachable_pub, + unused_import_braces, + unused_lifetimes, + unused_qualifications, + unused_results, + unused_tuple_struct_fields, + variant_size_differences +)] +#![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::restriction)] +#![allow(clippy::blanket_clippy_restriction_lints)] // this is a test, so enable all restriction lints intentionally. +#![allow(clippy::exhaustive_structs, clippy::exhaustive_enums, clippy::single_char_lifetime_names)] // TODO + +pub mod basic { + include!("include/basic.rs"); + + pub mod inside_macro { + #[rustfmt::skip] + macro_rules! mac { + () => { + #[::pin_project::pin_project] + #[derive(Debug)] + pub struct DefaultStruct { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[::pin_project::pin_project( + project = DefaultStructNamedProj, + project_ref = DefaultStructNamedProjRef, + )] + #[derive(Debug)] + pub struct DefaultStructNamed { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[::pin_project::pin_project] + #[derive(Debug)] + pub struct DefaultTupleStruct(#[pin] pub T, pub U); + + #[::pin_project::pin_project( + project = DefaultTupleStructNamedProj, + project_ref = DefaultTupleStructNamedProjRef, + )] + #[derive(Debug)] + pub struct DefaultTupleStructNamed(#[pin] pub T, pub U); + + #[::pin_project::pin_project( + project = DefaultEnumProj, + project_ref = DefaultEnumProjRef, + )] + #[derive(Debug)] + pub enum DefaultEnum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, + } + + #[::pin_project::pin_project(PinnedDrop)] + #[derive(Debug)] + pub struct PinnedDropStruct { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[::pin_project::pinned_drop] + impl PinnedDrop for PinnedDropStruct { + fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} + } + + #[::pin_project::pin_project(PinnedDrop)] + #[derive(Debug)] + pub struct PinnedDropTupleStruct(#[pin] pub T, pub U); + + #[::pin_project::pinned_drop] + impl PinnedDrop for PinnedDropTupleStruct { + fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} + } + + #[::pin_project::pin_project( + PinnedDrop, + project = PinnedDropEnumProj, + project_ref = PinnedDropEnumProjRef, + )] + #[derive(Debug)] + pub enum PinnedDropEnum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, + } + + #[::pin_project::pinned_drop] + impl PinnedDrop for PinnedDropEnum { + fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} + } + + #[::pin_project::pin_project(project_replace)] + #[derive(Debug)] + pub struct ReplaceStruct { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[::pin_project::pin_project( + project = ReplaceStructNamedProj, + project_ref = ReplaceStructNamedProjRef, + project_replace = ReplaceStructNamedProjOwn, + )] + #[derive(Debug)] + pub struct ReplaceStructNamed { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[::pin_project::pin_project(project_replace)] + #[derive(Debug)] + pub struct ReplaceTupleStruct(#[pin] pub T, pub U); + + #[::pin_project::pin_project( + project = ReplaceTupleStructNamedProj, + project_ref = ReplaceTupleStructNamedProjRef, + project_replace = ReplaceTupleStructNamedProjOwn, + )] + #[derive(Debug)] + pub struct ReplaceTupleStructNamed(#[pin] pub T, pub U); + + #[::pin_project::pin_project( + project = ReplaceEnumProj, + project_ref = ReplaceEnumProjRef, + project_replace = ReplaceEnumProjOwn, + )] + #[derive(Debug)] + pub enum ReplaceEnum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, + } + + #[::pin_project::pin_project(UnsafeUnpin)] + #[derive(Debug)] + pub struct UnsafeUnpinStruct { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[::pin_project::pin_project(UnsafeUnpin)] + #[derive(Debug)] + pub struct UnsafeUnpinTupleStruct(#[pin] pub T, pub U); + + #[::pin_project::pin_project( + UnsafeUnpin, + project = UnsafeUnpinEnumProj, + project_ref = UnsafeUnpinEnumProjRef, + )] + #[derive(Debug)] + pub enum UnsafeUnpinEnum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, + } + + #[::pin_project::pin_project(!Unpin)] + #[derive(Debug)] + pub struct NotUnpinStruct { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[::pin_project::pin_project(!Unpin)] + #[derive(Debug)] + pub struct NotUnpinTupleStruct(#[pin] pub T, pub U); + + #[::pin_project::pin_project( + !Unpin, + project = NotUnpinEnumProj, + project_ref = NotUnpinEnumProjRef, + )] + #[derive(Debug)] + pub enum NotUnpinEnum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, + } + + #[allow(clippy::undocumented_unsafe_blocks)] + unsafe impl + ::pin_project::UnsafeUnpin for UnsafeUnpinStruct + { + } + #[allow(clippy::undocumented_unsafe_blocks)] + unsafe impl + ::pin_project::UnsafeUnpin for UnsafeUnpinTupleStruct + { + } + #[allow(clippy::undocumented_unsafe_blocks)] + unsafe impl + ::pin_project::UnsafeUnpin for UnsafeUnpinEnum + { + } + }; + } + + mac!(); + } +} + +pub mod forbid_unsafe { + #![forbid(unsafe_code)] + + include!("include/basic-safe-part.rs"); + + pub mod inside_macro { + #[rustfmt::skip] + macro_rules! mac { + () => { + #[::pin_project::pin_project] + #[derive(Debug)] + pub struct DefaultStruct { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[::pin_project::pin_project( + project = DefaultStructNamedProj, + project_ref = DefaultStructNamedProjRef, + )] + #[derive(Debug)] + pub struct DefaultStructNamed { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[::pin_project::pin_project] + #[derive(Debug)] + pub struct DefaultTupleStruct(#[pin] pub T, pub U); + + #[::pin_project::pin_project( + project = DefaultTupleStructNamedProj, + project_ref = DefaultTupleStructNamedProjRef, + )] + #[derive(Debug)] + pub struct DefaultTupleStructNamed(#[pin] pub T, pub U); + + #[::pin_project::pin_project( + project = DefaultEnumProj, + project_ref = DefaultEnumProjRef, + )] + #[derive(Debug)] + pub enum DefaultEnum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, + } + + #[::pin_project::pin_project(PinnedDrop)] + #[derive(Debug)] + pub struct PinnedDropStruct { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[::pin_project::pinned_drop] + impl PinnedDrop for PinnedDropStruct { + fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} + } + + #[::pin_project::pin_project(PinnedDrop)] + #[derive(Debug)] + pub struct PinnedDropTupleStruct(#[pin] pub T, pub U); + + #[::pin_project::pinned_drop] + impl PinnedDrop for PinnedDropTupleStruct { + fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} + } + + #[::pin_project::pin_project( + PinnedDrop, + project = PinnedDropEnumProj, + project_ref = PinnedDropEnumProjRef, + )] + #[derive(Debug)] + pub enum PinnedDropEnum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, + } + + #[::pin_project::pinned_drop] + impl PinnedDrop for PinnedDropEnum { + fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} + } + + #[::pin_project::pin_project(project_replace)] + #[derive(Debug)] + pub struct ReplaceStruct { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[::pin_project::pin_project( + project = ReplaceStructNamedProj, + project_ref = ReplaceStructNamedProjRef, + project_replace = ReplaceStructNamedProjOwn, + )] + #[derive(Debug)] + pub struct ReplaceStructNamed { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[::pin_project::pin_project(project_replace)] + #[derive(Debug)] + pub struct ReplaceTupleStruct(#[pin] pub T, pub U); + + #[::pin_project::pin_project( + project = ReplaceTupleStructNamedProj, + project_ref = ReplaceTupleStructNamedProjRef, + project_replace = ReplaceTupleStructNamedProjOwn, + )] + #[derive(Debug)] + pub struct ReplaceTupleStructNamed(#[pin] pub T, pub U); + + #[::pin_project::pin_project( + project = ReplaceEnumProj, + project_ref = ReplaceEnumProjRef, + project_replace = ReplaceEnumProjOwn, + )] + #[derive(Debug)] + pub enum ReplaceEnum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, + } + + #[::pin_project::pin_project(UnsafeUnpin)] + #[derive(Debug)] + pub struct UnsafeUnpinStruct { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[::pin_project::pin_project(UnsafeUnpin)] + #[derive(Debug)] + pub struct UnsafeUnpinTupleStruct(#[pin] pub T, pub U); + + #[::pin_project::pin_project( + UnsafeUnpin, + project = UnsafeUnpinEnumProj, + project_ref = UnsafeUnpinEnumProjRef, + )] + #[derive(Debug)] + pub enum UnsafeUnpinEnum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, + } + + #[::pin_project::pin_project(!Unpin)] + #[derive(Debug)] + pub struct NotUnpinStruct { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[::pin_project::pin_project(!Unpin)] + #[derive(Debug)] + pub struct NotUnpinTupleStruct(#[pin] pub T, pub U); + + #[::pin_project::pin_project( + !Unpin, + project = NotUnpinEnumProj, + project_ref = NotUnpinEnumProjRef, + )] + #[derive(Debug)] + pub enum NotUnpinEnum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, + } + }; + } + + mac!(); + } +} + +pub mod box_pointers { + use pin_project::pin_project; + + #[allow(box_pointers)] // for the type itself + #[pin_project(project_replace)] + #[derive(Debug)] + pub struct Struct { + #[pin] + pub p: Box, + pub u: Box, + } + + #[allow(box_pointers)] // for the type itself + #[pin_project(project_replace)] + #[derive(Debug)] + pub struct TupleStruct(#[pin] pub Box, pub Box); + + #[allow(box_pointers)] // for the type itself + #[pin_project( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn, + )] + #[derive(Debug)] + pub enum Enum { + Struct { + #[pin] + p: Box, + u: Box, + }, + Tuple(#[pin] Box, Box), + Unit, + } + + pub mod inside_macro { + use pin_project::pin_project; + + #[rustfmt::skip] + macro_rules! mac { + () => { + #[allow(box_pointers)] // for the type itself + #[pin_project(project_replace)] + #[derive(Debug)] + pub struct Struct { + #[pin] + pub p: Box, + pub u: Box, + } + + #[allow(box_pointers)] // for the type itself + #[pin_project(project_replace)] + #[derive(Debug)] + pub struct TupleStruct(#[pin] pub Box, pub Box); + + #[allow(box_pointers)] // for the type itself + #[pin_project( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn, + )] + #[derive(Debug)] + pub enum Enum { + Struct { + #[pin] + p: Box, + u: Box, + }, + Tuple(#[pin] Box, Box), + Unit, + } + }; + } + + mac!(); + } +} + +pub mod deprecated { + use pin_project::pin_project; + + #[allow(deprecated)] // for the type itself + #[pin_project(project_replace)] + #[derive(Debug, Clone, Copy)] + #[deprecated] + pub struct Struct { + #[deprecated] + #[pin] + pub p: (), + #[deprecated] + pub u: (), + } + + #[allow(deprecated)] // for the type itself + #[pin_project(project_replace)] + #[derive(Debug, Clone, Copy)] + #[deprecated] + pub struct TupleStruct( + #[deprecated] + #[pin] + pub (), + #[deprecated] pub (), + ); + + #[allow(deprecated)] // for the type itself + #[pin_project( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn, + )] + #[derive(Debug, Clone, Copy)] + #[deprecated] + pub enum Enum { + #[deprecated] + Struct { + #[deprecated] + #[pin] + p: (), + #[deprecated] + u: (), + }, + #[deprecated] + Tuple( + #[deprecated] + #[pin] + (), + #[deprecated] (), + ), + #[deprecated] + Unit, + } + + pub mod inside_macro { + use pin_project::pin_project; + + #[rustfmt::skip] + macro_rules! mac { + () => { + #[allow(deprecated)] // for the type itself + #[pin_project(project_replace)] + #[derive(Debug, Clone, Copy)] + #[deprecated] + pub struct Struct { + #[deprecated] + #[pin] + pub p: (), + #[deprecated] + pub u: (), + } + + #[allow(deprecated)] // for the type itself + #[pin_project(project_replace)] + #[derive(Debug, Clone, Copy)] + #[deprecated] + pub struct TupleStruct( + #[deprecated] + #[pin] + pub (), + #[deprecated] pub (), + ); + + #[allow(deprecated)] // for the type itself + #[pin_project( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn, + )] + #[derive(Debug, Clone, Copy)] + #[deprecated] + pub enum Enum { + #[deprecated] + Struct { + #[deprecated] + #[pin] + p: (), + #[deprecated] + u: (), + }, + #[deprecated] + Tuple( + #[deprecated] + #[pin] + (), + #[deprecated] (), + ), + #[deprecated] + Unit, + } + }; + } + + mac!(); + } +} + +pub mod explicit_outlives_requirements { + use pin_project::pin_project; + + #[allow(explicit_outlives_requirements)] // for the type itself: https://github.com/rust-lang/rust/issues/60993 + #[pin_project(project_replace)] + #[derive(Debug)] + pub struct Struct<'a, T, U> + where + T: ?Sized, + U: ?Sized, + { + #[pin] + pub pinned: &'a mut T, + pub unpinned: &'a mut U, + } + + #[allow(explicit_outlives_requirements)] // for the type itself: https://github.com/rust-lang/rust/issues/60993 + #[pin_project(project_replace)] + #[derive(Debug)] + pub struct TupleStruct<'a, T, U>(#[pin] pub &'a mut T, pub &'a mut U) + where + T: ?Sized, + U: ?Sized; + + #[allow(explicit_outlives_requirements)] // for the type itself: https://github.com/rust-lang/rust/issues/60993 + #[pin_project( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn, + )] + #[derive(Debug)] + pub enum Enum<'a, T, U> + where + T: ?Sized, + U: ?Sized, + { + Struct { + #[pin] + pinned: &'a mut T, + unpinned: &'a mut U, + }, + Tuple(#[pin] &'a mut T, &'a mut U), + Unit, + } + + pub mod inside_macro { + use pin_project::pin_project; + + #[rustfmt::skip] + macro_rules! mac { + () => { + #[allow(explicit_outlives_requirements)] // for the type itself: https://github.com/rust-lang/rust/issues/60993 + #[pin_project(project_replace)] + #[derive(Debug)] + pub struct Struct<'a, T, U> + where + T: ?Sized, + U: ?Sized, + { + #[pin] + pub pinned: &'a mut T, + pub unpinned: &'a mut U, + } + + #[allow(explicit_outlives_requirements)] // for the type itself: https://github.com/rust-lang/rust/issues/60993 + #[pin_project(project_replace)] + #[derive(Debug)] + pub struct TupleStruct<'a, T, U>(#[pin] pub &'a mut T, pub &'a mut U) + where + T: ?Sized, + U: ?Sized; + + #[allow(explicit_outlives_requirements)] // for the type itself: https://github.com/rust-lang/rust/issues/60993 + #[pin_project( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn, + )] + #[derive(Debug)] + pub enum Enum<'a, T, U> + where + T: ?Sized, + U: ?Sized, + { + Struct { + #[pin] + pinned: &'a mut T, + unpinned: &'a mut U, + }, + Tuple(#[pin] &'a mut T, &'a mut U), + Unit, + } + }; + } + + mac!(); + } +} + +#[allow(missing_debug_implementations)] +pub mod single_use_lifetimes { + use pin_project::pin_project; + + #[allow(unused_lifetimes)] + pub trait Trait<'a> {} + + #[allow(unused_lifetimes)] // for the type itself + #[allow(single_use_lifetimes)] // for the type itself: https://github.com/rust-lang/rust/issues/55058 + #[pin_project(project_replace)] + pub struct Hrtb<'pin___, T> + where + for<'pin> &'pin T: Unpin, + T: for<'pin> Trait<'pin>, + for<'pin, 'pin_, 'pin__> &'pin &'pin_ &'pin__ T: Unpin, + { + #[pin] + _f: &'pin___ mut T, + } + + pub mod inside_macro { + use pin_project::pin_project; + + #[rustfmt::skip] + macro_rules! mac { + () => { + #[allow(unused_lifetimes)] + pub trait Trait<'a> {} + + #[allow(unused_lifetimes)] // for the type itself + #[allow(single_use_lifetimes)] // for the type itself: https://github.com/rust-lang/rust/issues/55058 + #[pin_project(project_replace)] + pub struct Hrtb<'pin___, T> + where + for<'pin> &'pin T: Unpin, + T: for<'pin> Trait<'pin>, + for<'pin, 'pin_, 'pin__> &'pin &'pin_ &'pin__ T: Unpin, + { + #[pin] + _f: &'pin___ mut T, + } + }; + } + + mac!(); + } +} + +pub mod variant_size_differences { + use pin_project::pin_project; + + #[allow(missing_debug_implementations, missing_copy_implementations)] // https://github.com/rust-lang/rust/pull/74060 + #[allow(variant_size_differences)] // for the type itself + #[allow(clippy::large_enum_variant)] // for the type itself + #[pin_project( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn, + )] + pub enum Enum { + V1(u8), + V2([u8; 1024]), + } + + pub mod inside_macro { + use pin_project::pin_project; + + #[rustfmt::skip] + macro_rules! mac { + () => { + #[allow(missing_debug_implementations, missing_copy_implementations)] // https://github.com/rust-lang/rust/pull/74060 + #[allow(variant_size_differences)] // for the type itself + #[allow(clippy::large_enum_variant)] // for the type itself + #[pin_project( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn, + )] + pub enum Enum { + V1(u8), + V2([u8; 1024]), + } + }; + } + + mac!(); + } +} + +pub mod clippy_mut_mut { + use pin_project::pin_project; + + #[pin_project(project_replace)] + #[derive(Debug)] + pub struct Struct<'a, T, U> { + #[pin] + pub pinned: &'a mut T, + pub unpinned: &'a mut U, + } + + #[pin_project(project_replace)] + #[derive(Debug)] + pub struct TupleStruct<'a, T, U>(#[pin] &'a mut T, &'a mut U); + + #[pin_project( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn, + )] + #[derive(Debug)] + pub enum Enum<'a, T, U> { + Struct { + #[pin] + pinned: &'a mut T, + unpinned: &'a mut U, + }, + Tuple(#[pin] &'a mut T, &'a mut U), + Unit, + } + + pub mod inside_macro { + use pin_project::pin_project; + + #[rustfmt::skip] + macro_rules! mac { + () => { + #[pin_project(project_replace)] + #[derive(Debug)] + pub struct Struct<'a, T, U> { + #[pin] + pub pinned: &'a mut T, + pub unpinned: &'a mut U, + } + + #[pin_project(project_replace)] + #[derive(Debug)] + pub struct TupleStruct<'a, T, U>(#[pin] &'a mut T, &'a mut U); + + #[pin_project( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn, + )] + #[derive(Debug)] + pub enum Enum<'a, T, U> { + Struct { + #[pin] + pinned: &'a mut T, + unpinned: &'a mut U, + }, + Tuple(#[pin] &'a mut T, &'a mut U), + Unit, + } + }; + } + + mac!(); + } +} + +#[allow(missing_debug_implementations)] +#[allow(unreachable_pub)] +mod clippy_redundant_pub_crate { + use pin_project::pin_project; + + #[pin_project(project_replace)] + pub struct Struct { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[pin_project(project_replace)] + pub struct TupleStruct(#[pin] pub T, pub U); + + #[allow(dead_code)] + #[pin_project( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn, + )] + pub enum Enum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, + } + + pub mod inside_macro { + use pin_project::pin_project; + + #[allow(clippy::redundant_pub_crate)] + #[rustfmt::skip] + macro_rules! mac { + () => { + #[pin_project(project_replace)] + pub struct Struct { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[pin_project(project_replace)] + pub struct TupleStruct(#[pin] pub T, pub U); + + #[allow(dead_code)] + #[pin_project( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn, + )] + pub enum Enum { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, + } + }; + } + + mac!(); + } +} + +#[allow(missing_debug_implementations)] +pub mod clippy_type_repetition_in_bounds { + use pin_project::pin_project; + + #[pin_project(project_replace)] + pub struct Struct + where + Self: Sized, + { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[pin_project(project_replace)] + pub struct TupleStruct(#[pin] T, U) + where + Self: Sized; + + #[pin_project( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn, + )] + pub enum Enum + where + Self: Sized, + { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, + } + + pub mod inside_macro { + use pin_project::pin_project; + + #[rustfmt::skip] + macro_rules! mac { + () => { + #[pin_project(project_replace)] + pub struct Struct + where + Self: Sized, + { + #[pin] + pub pinned: T, + pub unpinned: U, + } + + #[pin_project(project_replace)] + pub struct TupleStruct(#[pin] T, U) + where + Self: Sized; + + #[pin_project( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn, + )] + pub enum Enum + where + Self: Sized, + { + Struct { + #[pin] + pinned: T, + unpinned: U, + }, + Tuple(#[pin] T, U), + Unit, + } + }; + } + + mac!(); + } +} + +#[allow(missing_debug_implementations)] +pub mod clippy_use_self { + use pin_project::pin_project; + + pub trait Trait { + type Assoc; + } + + #[pin_project(project_replace)] + pub struct Generics> + where + Self: Trait, + { + _f: T, + } + + pub mod inside_macro { + use pin_project::pin_project; + + use super::Trait; + + #[rustfmt::skip] + macro_rules! mac { + () => { + #[pin_project(project_replace)] + pub struct Generics> + where + Self: Trait, + { + _f: T, + } + }; + } + + mac!(); + } +} + +#[allow(missing_debug_implementations)] +pub mod clippy_used_underscore_binding { + use pin_project::pin_project; + + #[pin_project(project_replace)] + pub struct Struct { + #[pin] + pub _pinned: T, + pub _unpinned: U, + } + + #[pin_project( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn, + )] + pub enum Enum { + Struct { + #[pin] + _pinned: T, + _unpinned: U, + }, + } + + pub mod inside_macro { + use pin_project::pin_project; + + #[rustfmt::skip] + macro_rules! mac { + () => { + #[pin_project(project_replace)] + pub struct Struct { + #[pin] + pub _pinned: T, + pub _unpinned: U, + } + + #[pin_project( + project = EnumProj, + project_ref = EnumProjRef, + project_replace = EnumProjOwn, + )] + pub enum Enum { + Struct { + #[pin] + _pinned: T, + _unpinned: U, + }, + } + }; + } + + mac!(); + } +} + +#[allow(missing_debug_implementations)] +pub mod clippy_ref_option_ref { + use pin_project::pin_project; + + #[pin_project] + pub struct Struct<'a> { + #[pin] + pub _pinned: Option<&'a ()>, + pub _unpinned: Option<&'a ()>, + } + + #[pin_project(project = EnumProj, project_ref = EnumProjRef)] + pub enum Enum<'a> { + Struct { + #[pin] + _pinned: Option<&'a ()>, + _unpinned: Option<&'a ()>, + }, + } +} diff --git a/tests/pin_project.rs b/tests/pin_project.rs new file mode 100644 index 0000000..aa08056 --- /dev/null +++ b/tests/pin_project.rs @@ -0,0 +1,887 @@ +#![warn(rust_2018_idioms, single_use_lifetimes)] +#![allow(dead_code)] + +#[macro_use] +mod auxiliary; + +use std::{ + marker::{PhantomData, PhantomPinned}, + panic, + pin::Pin, +}; + +use pin_project::{pin_project, pinned_drop, UnsafeUnpin}; + +#[test] +fn projection() { + #[pin_project( + project = StructProj, + project_ref = StructProjRef, + project_replace = StructProjOwn, + )] + struct Struct { + #[pin] + f1: T, + f2: U, + } + + let mut s = Struct { f1: 1, f2: 2 }; + let mut s_orig = Pin::new(&mut s); + let s = s_orig.as_mut().project(); + + let _: Pin<&mut i32> = s.f1; + assert_eq!(*s.f1, 1); + let _: &mut i32 = s.f2; + assert_eq!(*s.f2, 2); + + assert_eq!(s_orig.as_ref().f1, 1); + assert_eq!(s_orig.as_ref().f2, 2); + + let mut s = Struct { f1: 1, f2: 2 }; + let mut s = Pin::new(&mut s); + { + let StructProj { f1, f2 } = s.as_mut().project(); + let _: Pin<&mut i32> = f1; + let _: &mut i32 = f2; + } + { + let StructProjRef { f1, f2 } = s.as_ref().project_ref(); + let _: Pin<&i32> = f1; + let _: &i32 = f2; + } + { + let StructProjOwn { f1, f2 } = s.as_mut().project_replace(Struct { f1: 3, f2: 4 }); + let _: PhantomData = f1; + let _: i32 = f2; + assert_eq!(f2, 2); + assert_eq!(s.f1, 3); + assert_eq!(s.f2, 4); + } + + #[pin_project(project_replace)] + struct TupleStruct(#[pin] T, U); + + let mut s = TupleStruct(1, 2); + let s = Pin::new(&mut s).project(); + + let _: Pin<&mut i32> = s.0; + assert_eq!(*s.0, 1); + let _: &mut i32 = s.1; + assert_eq!(*s.1, 2); + + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] + #[derive(Eq, PartialEq, Debug)] + enum Enum { + Tuple(#[pin] A, B), + Struct { + #[pin] + f1: C, + f2: D, + }, + Unit, + } + + let mut e = Enum::Tuple(1, 2); + let mut e = Pin::new(&mut e); + + match e.as_mut().project() { + EnumProj::Tuple(x, y) => { + let x: Pin<&mut i32> = x; + assert_eq!(*x, 1); + let y: &mut i32 = y; + assert_eq!(*y, 2); + } + EnumProj::Struct { f1, f2 } => { + let _: Pin<&mut i32> = f1; + let _: &mut i32 = f2; + unreachable!(); + } + EnumProj::Unit => unreachable!(), + } + + assert_eq!(&*e, &Enum::Tuple(1, 2)); + + let mut e = Enum::Struct { f1: 3, f2: 4 }; + let mut e = Pin::new(&mut e); + + match e.as_mut().project() { + EnumProj::Tuple(x, y) => { + let _: Pin<&mut i32> = x; + let _: &mut i32 = y; + unreachable!(); + } + EnumProj::Struct { f1, f2 } => { + let _: Pin<&mut i32> = f1; + assert_eq!(*f1, 3); + let _: &mut i32 = f2; + assert_eq!(*f2, 4); + } + EnumProj::Unit => unreachable!(), + } + + if let EnumProj::Struct { f1, f2 } = e.as_mut().project() { + let _: Pin<&mut i32> = f1; + assert_eq!(*f1, 3); + let _: &mut i32 = f2; + assert_eq!(*f2, 4); + } +} + +#[test] +fn enum_project_set() { + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] + #[derive(Eq, PartialEq, Debug)] + enum Enum { + V1(#[pin] u8), + V2(bool), + } + + let mut e = Enum::V1(25); + let mut e_orig = Pin::new(&mut e); + let e_proj = e_orig.as_mut().project(); + + match e_proj { + EnumProj::V1(val) => { + let new_e = Enum::V2(val.as_ref().get_ref() == &25); + e_orig.set(new_e); + } + EnumProj::V2(_) => unreachable!(), + } + + assert_eq!(e, Enum::V2(true)); +} + +#[test] +fn where_clause() { + #[pin_project] + struct Struct + where + T: Copy, + { + f: T, + } + + #[pin_project] + struct TupleStruct(T) + where + T: Copy; + + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] + enum Enum + where + T: Copy, + { + V(T), + } +} + +#[test] +fn where_clause_and_associated_type_field() { + #[pin_project(project_replace)] + struct Struct1 + where + I: Iterator, + { + #[pin] + f1: I, + f2: I::Item, + } + + #[pin_project(project_replace)] + struct Struct2 + where + I: Iterator, + { + #[pin] + f1: I, + f2: J, + } + + #[pin_project(project_replace)] + struct Struct3 + where + T: 'static, + { + f: T, + } + + trait Static: 'static {} + + impl Static for Struct3 {} + + #[pin_project(project_replace)] + struct TupleStruct(#[pin] I, I::Item) + where + I: Iterator; + + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] + enum Enum + where + I: Iterator, + { + V1(#[pin] I), + V2(I::Item), + } +} + +#[test] +fn derive_copy() { + #[pin_project(project_replace)] + #[derive(Clone, Copy)] + struct Struct { + f: T, + } + + fn is_copy() {} + + is_copy::>(); +} + +#[test] +fn move_out() { + struct NotCopy; + + #[pin_project(project_replace)] + struct Struct { + f: NotCopy, + } + + let x = Struct { f: NotCopy }; + let _val: NotCopy = x.f; + + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] + enum Enum { + V(NotCopy), + } + + let x = Enum::V(NotCopy); + #[allow(clippy::infallible_destructuring_match)] + let _val: NotCopy = match x { + Enum::V(val) => val, + }; +} + +#[test] +fn trait_bounds_on_type_generics() { + #[pin_project(project_replace)] + pub struct Struct1<'a, T: ?Sized> { + f: &'a mut T, + } + + #[pin_project(project_replace)] + pub struct Struct2<'a, T: ::core::fmt::Debug> { + f: &'a mut T, + } + + #[pin_project(project_replace)] + pub struct Struct3<'a, T: core::fmt::Debug> { + f: &'a mut T, + } + + #[pin_project(project_replace)] + pub struct Struct4<'a, T: core::fmt::Debug + core::fmt::Display> { + f: &'a mut T, + } + + #[pin_project(project_replace)] + pub struct Struct5<'a, T: core::fmt::Debug + ?Sized> { + f: &'a mut T, + } + + #[pin_project(project_replace)] + pub struct Struct6<'a, T: core::fmt::Debug = [u8; 16]> { + f: &'a mut T, + } + + let _: Struct6<'_> = Struct6 { f: &mut [0_u8; 16] }; + + #[pin_project(project_replace)] + pub struct Struct7 { + f: T, + } + + trait Static: 'static {} + + impl Static for Struct7 {} + + #[pin_project(project_replace)] + pub struct Struct8<'a, 'b: 'a> { + f1: &'a u8, + f2: &'b u8, + } + + #[pin_project(project_replace)] + pub struct TupleStruct<'a, T: ?Sized>(&'a mut T); + + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] + enum Enum<'a, T: ?Sized> { + V(&'a mut T), + } +} + +#[test] +fn overlapping_lifetime_names() { + #[pin_project(project_replace)] + pub struct Struct1<'pin, T> { + #[pin] + f: &'pin mut T, + } + + #[pin_project(project_replace)] + pub struct Struct2<'pin, 'pin_, 'pin__> { + #[pin] + f: &'pin &'pin_ &'pin__ (), + } + + pub trait Trait<'a> {} + + #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058 + #[pin_project(project_replace)] + pub struct Hrtb<'pin___, T> + where + for<'pin> &'pin T: Unpin, + T: for<'pin> Trait<'pin>, + for<'pin, 'pin_, 'pin__> &'pin &'pin_ &'pin__ T: Unpin, + { + #[pin] + f: &'pin___ mut T, + } + + #[pin_project(PinnedDrop)] + pub struct PinnedDropStruct<'pin> { + #[pin] + f: &'pin (), + } + + #[pinned_drop] + impl PinnedDrop for PinnedDropStruct<'_> { + fn drop(self: Pin<&mut Self>) {} + } + + #[pin_project(UnsafeUnpin)] + pub struct UnsafeUnpinStruct<'pin> { + #[pin] + f: &'pin (), + } + + unsafe impl UnsafeUnpin for UnsafeUnpinStruct<'_> {} + + #[pin_project(!Unpin)] + pub struct NotUnpinStruct<'pin> { + #[pin] + f: &'pin (), + } +} + +#[test] +fn combine() { + #[pin_project(PinnedDrop, UnsafeUnpin)] + pub struct PinnedDropWithUnsafeUnpin { + #[pin] + f: T, + } + + #[pinned_drop] + impl PinnedDrop for PinnedDropWithUnsafeUnpin { + fn drop(self: Pin<&mut Self>) {} + } + + unsafe impl UnsafeUnpin for PinnedDropWithUnsafeUnpin {} + + #[pin_project(PinnedDrop, !Unpin)] + pub struct PinnedDropWithNotUnpin { + #[pin] + f: T, + } + + #[pinned_drop] + impl PinnedDrop for PinnedDropWithNotUnpin { + fn drop(self: Pin<&mut Self>) {} + } + + #[pin_project(UnsafeUnpin, project_replace)] + pub struct UnsafeUnpinWithReplace { + #[pin] + f: T, + } + + unsafe impl UnsafeUnpin for UnsafeUnpinWithReplace {} + + #[pin_project(!Unpin, project_replace)] + pub struct NotUnpinWithReplace { + #[pin] + f: T, + } +} + +#[test] +fn private_type_in_public_type() { + #[pin_project(project_replace)] + pub struct PublicStruct { + #[pin] + inner: PrivateStruct, + } + + struct PrivateStruct(T); +} + +#[allow(clippy::needless_lifetimes)] +#[test] +fn lifetime_project() { + #[pin_project(project_replace)] + struct Struct1 { + #[pin] + pinned: T, + unpinned: U, + } + + #[pin_project(project_replace)] + struct Struct2<'a, T, U> { + #[pin] + pinned: &'a T, + unpinned: U, + } + + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] + enum Enum { + V { + #[pin] + pinned: T, + unpinned: U, + }, + } + + impl Struct1 { + fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a T> { + self.project_ref().pinned + } + fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut T> { + self.project().pinned + } + fn get_pin_ref_elided(self: Pin<&Self>) -> Pin<&T> { + self.project_ref().pinned + } + fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut T> { + self.project().pinned + } + } + + impl<'b, T, U> Struct2<'b, T, U> { + fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a &'b T> { + self.project_ref().pinned + } + fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut &'b T> { + self.project().pinned + } + fn get_pin_ref_elided(self: Pin<&Self>) -> Pin<&&'b T> { + self.project_ref().pinned + } + fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut &'b T> { + self.project().pinned + } + } + + impl Enum { + fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a T> { + match self.project_ref() { + EnumProjRef::V { pinned, .. } => pinned, + } + } + fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut T> { + match self.project() { + EnumProj::V { pinned, .. } => pinned, + } + } + fn get_pin_ref_elided(self: Pin<&Self>) -> Pin<&T> { + match self.project_ref() { + EnumProjRef::V { pinned, .. } => pinned, + } + } + fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut T> { + match self.project() { + EnumProj::V { pinned, .. } => pinned, + } + } + } +} + +mod visibility { + use pin_project::pin_project; + + #[pin_project(project_replace)] + pub(crate) struct S { + pub f: u8, + } +} + +#[test] +fn visibility() { + let mut x = visibility::S { f: 0 }; + let x = Pin::new(&mut x); + let y = x.as_ref().project_ref(); + let _: &u8 = y.f; + let y = x.project(); + let _: &mut u8 = y.f; +} + +#[test] +fn trivial_bounds() { + #[pin_project(project_replace)] + pub struct NoGenerics { + #[pin] + f: PhantomPinned, + } + + assert_not_unpin!(NoGenerics); +} + +#[test] +fn dst() { + #[pin_project] + struct Struct1 { + f: T, + } + + let mut x = Struct1 { f: 0_u8 }; + let x: Pin<&mut Struct1> = Pin::new(&mut x as _); + let _: &mut (dyn core::fmt::Debug) = x.project().f; + + #[pin_project] + struct Struct2 { + #[pin] + f: T, + } + + let mut x = Struct2 { f: 0_u8 }; + let x: Pin<&mut Struct2> = Pin::new(&mut x as _); + let _: Pin<&mut (dyn core::fmt::Debug + Unpin)> = x.project().f; + + #[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993 + #[pin_project] + struct Struct3 + where + T: ?Sized, + { + f: T, + } + + #[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993 + #[pin_project] + struct Struct4 + where + T: ?Sized, + { + #[pin] + f: T, + } + + #[pin_project(UnsafeUnpin)] + struct Struct5 { + f: T, + } + + #[pin_project(UnsafeUnpin)] + struct Struct6 { + #[pin] + f: T, + } + + #[pin_project(PinnedDrop)] + struct Struct7 { + f: T, + } + + #[pinned_drop] + impl PinnedDrop for Struct7 { + fn drop(self: Pin<&mut Self>) {} + } + + #[pin_project(PinnedDrop)] + struct Struct8 { + #[pin] + f: T, + } + + #[pinned_drop] + impl PinnedDrop for Struct8 { + fn drop(self: Pin<&mut Self>) {} + } + + #[pin_project(!Unpin)] + struct Struct9 { + f: T, + } + + #[pin_project(!Unpin)] + struct Struct10 { + #[pin] + f: T, + } + + #[pin_project] + struct Struct11<'a, T: ?Sized, U: ?Sized> { + f1: &'a mut T, + f2: U, + } + + #[pin_project] + struct TupleStruct1(T); + + #[pin_project] + struct TupleStruct2(#[pin] T); + + #[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993 + #[pin_project] + struct TupleStruct3(T) + where + T: ?Sized; + + #[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993 + #[pin_project] + struct TupleStruct4(#[pin] T) + where + T: ?Sized; + + #[pin_project(UnsafeUnpin)] + struct TupleStruct5(T); + + #[pin_project(UnsafeUnpin)] + struct TupleStruct6(#[pin] T); + + #[pin_project(PinnedDrop)] + struct TupleStruct7(T); + + #[pinned_drop] + impl PinnedDrop for TupleStruct7 { + fn drop(self: Pin<&mut Self>) {} + } + + #[pin_project(PinnedDrop)] + struct TupleStruct8(#[pin] T); + + #[pinned_drop] + impl PinnedDrop for TupleStruct8 { + fn drop(self: Pin<&mut Self>) {} + } + + #[pin_project(!Unpin)] + struct TupleStruct9(T); + + #[pin_project(!Unpin)] + struct TupleStruct10(#[pin] T); + + #[pin_project] + struct TupleStruct11<'a, T: ?Sized, U: ?Sized>(&'a mut T, U); +} + +#[test] +fn dyn_type() { + #[pin_project] + struct Struct1 { + f: dyn core::fmt::Debug, + } + + #[pin_project] + struct Struct2 { + #[pin] + f: dyn core::fmt::Debug, + } + + #[pin_project] + struct Struct3 { + f: dyn core::fmt::Debug + Send, + } + + #[pin_project] + struct Struct4 { + #[pin] + f: dyn core::fmt::Debug + Send, + } + + #[pin_project] + struct TupleStruct1(dyn core::fmt::Debug); + + #[pin_project] + struct TupleStruct2(#[pin] dyn core::fmt::Debug); + + #[pin_project] + struct TupleStruct3(dyn core::fmt::Debug + Send); + + #[pin_project] + struct TupleStruct4(#[pin] dyn core::fmt::Debug + Send); +} + +#[test] +fn parse_self() { + macro_rules! mac { + ($($tt:tt)*) => { + $($tt)* + }; + } + + pub trait Trait { + type Assoc; + } + + #[allow(clippy::type_repetition_in_bounds)] + #[pin_project(project_replace)] + pub struct Generics> + where + Self: Trait, + ::Assoc: Sized, + mac!(Self): Trait, + { + _f: T, + } + + impl> Trait for Generics { + type Assoc = Self; + } + + #[pin_project(project_replace)] + pub struct Struct { + _f1: Box, + _f2: Box<::Assoc>, + _f3: Box, + _f4: [(); Self::ASSOC], + _f5: [(); Self::assoc()], + _f6: [(); mac!(Self::assoc())], + } + + impl Struct { + const ASSOC: usize = 1; + const fn assoc() -> usize { + 0 + } + } + + impl Trait for Struct { + type Assoc = Self; + } + + #[pin_project(project_replace)] + struct Tuple( + Box, + Box<::Assoc>, + Box, + [(); Self::ASSOC], + [(); Self::assoc()], + [(); mac!(Self::assoc())], + ); + + impl Tuple { + const ASSOC: usize = 1; + const fn assoc() -> usize { + 0 + } + } + + impl Trait for Tuple { + type Assoc = Self; + } + + #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] + enum Enum { + Struct { + _f1: Box, + _f2: Box<::Assoc>, + _f3: Box, + _f4: [(); Self::ASSOC], + _f5: [(); Self::assoc()], + _f6: [(); mac!(Self::assoc())], + }, + Tuple( + Box, + Box<::Assoc>, + Box, + [(); Self::ASSOC], + [(); Self::assoc()], + [(); mac!(Self::assoc())], + ), + } + + impl Enum { + const ASSOC: usize = 1; + const fn assoc() -> usize { + 0 + } + } + + impl Trait for Enum { + type Assoc = Self; + } +} + +#[test] +fn no_infer_outlives() { + trait Trait { + type Y; + } + + struct Struct1(A); + + impl Trait for Struct1 { + type Y = Option; + } + + #[pin_project(project_replace)] + struct Struct2 { + _f: as Trait>::Y, + } +} + +// https://github.com/rust-lang/rust/issues/47949 +// https://github.com/taiki-e/pin-project/pull/194#discussion_r419098111 +#[allow(clippy::many_single_char_names)] +#[test] +fn project_replace_panic() { + #[pin_project(project_replace)] + struct S { + #[pin] + pinned: T, + unpinned: U, + } + + struct D<'a>(&'a mut bool, bool); + impl Drop for D<'_> { + fn drop(&mut self) { + *self.0 = true; + if self.1 { + panic!(); + } + } + } + + let (mut a, mut b, mut c, mut d) = (false, false, false, false); + let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { + let mut x = S { pinned: D(&mut a, true), unpinned: D(&mut b, false) }; + let _y = Pin::new(&mut x) + .project_replace(S { pinned: D(&mut c, false), unpinned: D(&mut d, false) }); + // Previous `x.pinned` was dropped and panicked when `project_replace` is + // called, so this is unreachable. + unreachable!(); + })); + assert!(res.is_err()); + assert!(a); + assert!(b); + assert!(c); + assert!(d); + + let (mut a, mut b, mut c, mut d) = (false, false, false, false); + let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { + let mut x = S { pinned: D(&mut a, false), unpinned: D(&mut b, true) }; + { + let _y = Pin::new(&mut x) + .project_replace(S { pinned: D(&mut c, false), unpinned: D(&mut d, false) }); + // `_y` (previous `x.unpinned`) live to the end of this scope, so + // this is not unreachable. + // unreachable!(); + } + unreachable!(); + })); + assert!(res.is_err()); + assert!(a); + assert!(b); + assert!(c); + assert!(d); +} diff --git a/tests/pinned_drop.rs b/tests/pinned_drop.rs new file mode 100644 index 0000000..99273c4 --- /dev/null +++ b/tests/pinned_drop.rs @@ -0,0 +1,284 @@ +#![warn(rust_2018_idioms, single_use_lifetimes)] + +use std::pin::Pin; + +use pin_project::{pin_project, pinned_drop}; + +#[test] +fn safe_project() { + #[pin_project(PinnedDrop)] + pub struct Struct<'a> { + was_dropped: &'a mut bool, + #[pin] + field: u8, + } + + #[pinned_drop] + impl PinnedDrop for Struct<'_> { + fn drop(self: Pin<&mut Self>) { + **self.project().was_dropped = true; + } + } + + let mut was_dropped = false; + drop(Struct { was_dropped: &mut was_dropped, field: 42 }); + assert!(was_dropped); +} + +#[test] +fn self_call() { + #[pin_project(PinnedDrop)] + pub struct S(T); + + trait Trait { + fn self_ref(&self) {} + fn self_pin_ref(self: Pin<&Self>) {} + fn self_mut(&mut self) {} + fn self_pin_mut(self: Pin<&mut Self>) {} + fn assoc_fn(_this: Pin<&mut Self>) {} + } + + impl Trait for S {} + + #[pinned_drop] + impl PinnedDrop for S { + fn drop(mut self: Pin<&mut Self>) { + self.self_ref(); + self.as_ref().self_pin_ref(); + self.self_mut(); + self.as_mut().self_pin_mut(); + Self::assoc_fn(self.as_mut()); + ::assoc_fn(self.as_mut()); + } + } +} + +#[test] +fn self_ty() { + #[pin_project(PinnedDrop)] + pub struct Struct { + pub f: (), + } + + #[pinned_drop] + impl PinnedDrop for Struct { + #[allow(irrefutable_let_patterns)] + #[allow(clippy::match_single_binding)] + fn drop(mut self: Pin<&mut Self>) { + // expr + let _: Self = Self { f: () }; + + // pat + match *self { + Self { f: () } => {} + } + if let Self { f: () } = *self {} + let Self { f: () } = *self; + } + } + + #[pin_project(PinnedDrop)] + pub struct TupleStruct(()); + + #[pinned_drop] + impl PinnedDrop for TupleStruct { + #[allow(irrefutable_let_patterns)] + fn drop(mut self: Pin<&mut Self>) { + // expr + let _: Self = Self(()); + + // pat + match *self { + Self(_) => {} + } + if let Self(_) = *self {} + let Self(_) = *self; + } + } + + #[pin_project(PinnedDrop, project = EnumProj, project_ref = EnumProjRef)] + pub enum Enum { + Struct { f: () }, + Tuple(()), + Unit, + } + + #[pinned_drop] + impl PinnedDrop for Enum { + fn drop(mut self: Pin<&mut Self>) { + // expr + let _: Self = Self::Struct { f: () }; + let _: Self = Self::Tuple(()); + let _: Self = Self::Unit; + + // pat + match *self { + Self::Struct { f: () } => {} + Self::Tuple(_) => {} + Self::Unit => {} + } + if let Self::Struct { f: () } = *self {} + if let Self::Tuple(_) = *self {} + if let Self::Unit = *self {} + } + } +} + +#[test] +fn self_inside_macro_containing_fn() { + macro_rules! mac { + ($($tt:tt)*) => { + $($tt)* + }; + } + + #[pin_project(PinnedDrop)] + pub struct S(()); + + #[pinned_drop] + impl PinnedDrop for S { + fn drop(self: Pin<&mut Self>) { + mac!({ + impl S { + pub fn _f(self) -> Self { + self + } + } + }); + } + } +} + +// See also `ui/pinned_drop/self.rs`. +#[rustversion::since(1.40)] // https://github.com/rust-lang/rust/pull/64690 +#[test] +fn self_inside_macro_def() { + #[pin_project(PinnedDrop)] + pub struct S(()); + + #[pinned_drop] + impl PinnedDrop for S { + fn drop(self: Pin<&mut Self>) { + macro_rules! mac { + () => {{ + let _ = self; + let _ = Self(()); + }}; + } + mac!(); + } + } +} + +#[test] +fn self_arg_inside_macro_call() { + #[pin_project(PinnedDrop)] + struct Struct { + f: (), + } + + #[pinned_drop] + impl PinnedDrop for Struct { + fn drop(self: Pin<&mut Self>) { + let _: Vec<_> = vec![self.f]; + } + } +} + +#[test] +fn self_ty_inside_macro_call() { + macro_rules! mac { + ($($tt:tt)*) => { + $($tt)* + }; + } + + #[pin_project(PinnedDrop)] + pub struct Struct + where + mac!(Self): Send, + { + _f: T, + } + + impl Struct { + const ASSOC1: usize = 1; + fn assoc1() {} + } + + trait Trait { + type Assoc2; + const ASSOC2: usize; + fn assoc2(); + } + + impl Trait for Struct { + type Assoc2 = u8; + const ASSOC2: usize = 2; + fn assoc2() {} + } + + #[pinned_drop] + impl PinnedDrop for Struct + where + mac!(Self): Send, + { + #[allow(path_statements)] + #[allow(clippy::no_effect)] + fn drop(self: Pin<&mut Self>) { + // inherent items + mac!(Self::ASSOC1;); + mac!(::ASSOC1;); + mac!(Self::assoc1();); + mac!(::assoc1();); + + // trait items + mac!(let _: ::Assoc2;); + mac!(Self::ASSOC2;); + mac!(::ASSOC2;); + mac!(::ASSOC2;); + mac!(Self::assoc2();); + mac!(::assoc2();); + mac!(::assoc2();); + } + } +} + +#[test] +fn inside_macro() { + #[pin_project(PinnedDrop)] + struct S(()); + + macro_rules! mac { + ($expr:expr) => { + #[pinned_drop] + impl PinnedDrop for S { + fn drop(self: Pin<&mut Self>) { + let _ = $expr; + } + } + }; + } + + mac!(1); +} + +pub mod self_path { + use super::*; + + #[pin_project(PinnedDrop)] + pub struct S(T); + + fn f() {} + + #[pinned_drop] + impl PinnedDrop for self::S { + fn drop(mut self: Pin<&mut Self>) { + self::f(); + let _: self::S<()> = self::S(()); + let _: self::S> = self::S(self.as_mut()); + let self::S(()) = self::S(()); + let self::S(&mut Self(_)) = self::S(&mut *self); + } + } +} diff --git a/tests/proper_unpin.rs b/tests/proper_unpin.rs new file mode 100644 index 0000000..0ba3ce3 --- /dev/null +++ b/tests/proper_unpin.rs @@ -0,0 +1,153 @@ +#![warn(rust_2018_idioms, single_use_lifetimes)] +#![allow(dead_code)] + +#[macro_use] +mod auxiliary; + +pub mod default { + use std::marker::PhantomPinned; + + use pin_project::pin_project; + + struct Inner { + f: T, + } + + assert_unpin!(Inner<()>); + assert_not_unpin!(Inner); + + #[pin_project] + struct Struct { + #[pin] + f1: Inner, + f2: U, + } + + assert_unpin!(Struct<(), ()>); + assert_unpin!(Struct<(), PhantomPinned>); + assert_not_unpin!(Struct); + assert_not_unpin!(Struct); + + #[pin_project(project = EnumProj, project_ref = EnumProjRef)] + enum Enum { + V1 { + #[pin] + f1: Inner, + f2: U, + }, + } + + assert_unpin!(Enum<(), ()>); + assert_unpin!(Enum<(), PhantomPinned>); + assert_not_unpin!(Enum); + assert_not_unpin!(Enum); + + #[pin_project] + struct TrivialBounds { + #[pin] + f: PhantomPinned, + } + + assert_not_unpin!(TrivialBounds); + + #[pin_project] + struct PinRef<'a, T, U> { + #[pin] + f1: &'a mut Inner, + f2: U, + } + + assert_unpin!(PinRef<'_, PhantomPinned, PhantomPinned>); +} + +pub mod cfg { + use std::marker::PhantomPinned; + + use pin_project::pin_project; + + #[pin_project] + struct Foo { + #[cfg(any())] + #[pin] + f: T, + #[cfg(not(any()))] + f: T, + } + + assert_unpin!(Foo); + + #[pin_project] + struct Bar { + #[cfg(any())] + f: T, + #[cfg(not(any()))] + #[pin] + f: T, + } + + assert_unpin!(Bar<()>); + assert_not_unpin!(Bar); +} + +pub mod cfg_attr { + use std::marker::PhantomPinned; + + use pin_project::pin_project; + + #[cfg_attr(any(), pin_project)] + struct Foo { + f: T, + } + + assert_unpin!(Foo<()>); + assert_not_unpin!(Foo); + + #[cfg_attr(not(any()), pin_project)] + struct Bar { + #[cfg_attr(not(any()), pin)] + f: T, + } + + assert_unpin!(Bar<()>); + assert_not_unpin!(Bar); +} + +// pin_project(!Unpin) +pub mod not_unpin { + use std::marker::PhantomPinned; + + use pin_project::pin_project; + + struct Inner { + f: T, + } + + #[pin_project(!Unpin)] + struct Struct { + #[pin] + inner: Inner, + other: U, + } + + assert_not_unpin!(Struct<(), ()>); + assert_not_unpin!(Struct<(), PhantomPinned>); + assert_not_unpin!(Struct); + assert_not_unpin!(Struct); + + #[pin_project(!Unpin)] + struct TrivialBounds { + #[pin] + f: PhantomPinned, + } + + assert_not_unpin!(TrivialBounds); + + #[pin_project(!Unpin)] + struct PinRef<'a, T, U> { + #[pin] + inner: &'a mut Inner, + other: U, + } + + assert_not_unpin!(PinRef<'_, (), ()>); +} diff --git a/tests/repr_packed.rs b/tests/repr_packed.rs new file mode 100644 index 0000000..be7cab9 --- /dev/null +++ b/tests/repr_packed.rs @@ -0,0 +1,52 @@ +#![warn(rust_2018_idioms, single_use_lifetimes)] +// unaligned_references did not exist in older compilers and safe_packed_borrows was removed in the latest compilers. +// https://github.com/rust-lang/rust/pull/82525 +#![allow(unknown_lints, renamed_and_removed_lints)] +#![forbid(unaligned_references, safe_packed_borrows)] + +use std::cell::Cell; + +// Ensure that the compiler doesn't copy the fields +// of #[repr(packed)] types during drop, if the field has alignment 1 +// (that is, any reference to the field is guaranteed to have proper alignment) +// We are currently unable to statically prevent the usage of #[pin_project] +// on #[repr(packed)] types composed entirely of fields of alignment 1. +// This shouldn't lead to undefined behavior, as long as the compiler doesn't +// try to move the field anyway during drop. +// +// This tests validates that the compiler is doing what we expect. +#[test] +fn weird_repr_packed() { + // We keep track of the field address during + // drop using a thread local, to avoid changing + // the layout of our #[repr(packed)] type. + thread_local! { + static FIELD_ADDR: Cell = Cell::new(0); + } + + #[repr(packed)] + struct Struct { + field: u8, + } + + impl Drop for Struct { + fn drop(&mut self) { + FIELD_ADDR.with(|f| { + f.set(&self.field as *const u8 as usize); + }); + } + } + + #[allow(clippy::let_and_return)] + let field_addr = { + // We let this field drop by going out of scope, + // rather than explicitly calling drop(foo). + // Calling drop(foo) causes 'foo' to be moved + // into the 'drop' function, resulting in a different + // address. + let x = Struct { field: 27 }; + let field_addr = &x.field as *const u8 as usize; + field_addr + }; + assert_eq!(field_addr, FIELD_ADDR.with(Cell::get)); +} diff --git a/tests/ui/cfg/cfg_attr-resolve.rs b/tests/ui/cfg/cfg_attr-resolve.rs new file mode 100644 index 0000000..e36cc95 --- /dev/null +++ b/tests/ui/cfg/cfg_attr-resolve.rs @@ -0,0 +1,11 @@ +use std::pin::Pin; + +#[cfg_attr(any(), pin_project::pin_project)] +struct Foo { + f: T, +} + +fn main() { + let mut x = Foo { f: 0_u8 }; + let _ = Pin::new(&mut x).project(); //~ ERROR E0599 +} diff --git a/tests/ui/cfg/cfg_attr-resolve.stderr b/tests/ui/cfg/cfg_attr-resolve.stderr new file mode 100644 index 0000000..0393c14 --- /dev/null +++ b/tests/ui/cfg/cfg_attr-resolve.stderr @@ -0,0 +1,5 @@ +error[E0599]: no method named `project` found for struct `Pin<&mut Foo>` in the current scope + --> tests/ui/cfg/cfg_attr-resolve.rs:10:30 + | +10 | let _ = Pin::new(&mut x).project(); //~ ERROR E0599 + | ^^^^^^^ method not found in `Pin<&mut Foo>` diff --git a/tests/ui/cfg/cfg_attr-type-mismatch.rs b/tests/ui/cfg/cfg_attr-type-mismatch.rs new file mode 100644 index 0000000..1b9664b --- /dev/null +++ b/tests/ui/cfg/cfg_attr-type-mismatch.rs @@ -0,0 +1,25 @@ +use std::pin::Pin; + +use pin_project::pin_project; + +#[cfg_attr(not(any()), pin_project)] +struct Foo { + #[cfg_attr(any(), pin)] + f: T, +} + +#[cfg_attr(not(any()), pin_project)] +struct Bar { + #[cfg_attr(not(any()), pin)] + f: T, +} + +fn main() { + let mut x = Foo { f: 0_u8 }; + let x = Pin::new(&mut x).project(); + let _: Pin<&mut u8> = x.f; //~ ERROR E0308 + + let mut x = Bar { f: 0_u8 }; + let x = Pin::new(&mut x).project(); + let _: &mut u8 = x.f; //~ ERROR E0308 +} diff --git a/tests/ui/cfg/cfg_attr-type-mismatch.stderr b/tests/ui/cfg/cfg_attr-type-mismatch.stderr new file mode 100644 index 0000000..366d9c7 --- /dev/null +++ b/tests/ui/cfg/cfg_attr-type-mismatch.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> tests/ui/cfg/cfg_attr-type-mismatch.rs:20:27 + | +20 | let _: Pin<&mut u8> = x.f; //~ ERROR E0308 + | ------------ ^^^ expected struct `Pin`, found `&mut u8` + | | + | expected due to this + | + = note: expected struct `Pin<&mut u8>` + found mutable reference `&mut u8` + +error[E0308]: mismatched types + --> tests/ui/cfg/cfg_attr-type-mismatch.rs:24:22 + | +24 | let _: &mut u8 = x.f; //~ ERROR E0308 + | ------- ^^^ + | | | + | | expected `&mut u8`, found struct `Pin` + | | help: consider mutably borrowing here: `&mut x.f` + | expected due to this + | + = note: expected mutable reference `&mut u8` + found struct `Pin<&mut u8>` diff --git a/tests/ui/cfg/packed_sneaky-span-issue-1.rs b/tests/ui/cfg/packed_sneaky-span-issue-1.rs new file mode 100644 index 0000000..7e19952 --- /dev/null +++ b/tests/ui/cfg/packed_sneaky-span-issue-1.rs @@ -0,0 +1,15 @@ +use auxiliary_macro::hidden_repr; +use pin_project::pin_project; + +#[pin_project] +#[hidden_repr(packed)] //~ ERROR may not be used on #[repr(packed)] types +struct S { + #[cfg(not(any()))] + #[pin] + f: u32, + #[cfg(any())] + #[pin] + f: u8, +} + +fn main() {} diff --git a/tests/ui/cfg/packed_sneaky-span-issue-1.stderr b/tests/ui/cfg/packed_sneaky-span-issue-1.stderr new file mode 100644 index 0000000..4f3acc3 --- /dev/null +++ b/tests/ui/cfg/packed_sneaky-span-issue-1.stderr @@ -0,0 +1,5 @@ +error: #[pin_project] attribute may not be used on #[repr(packed)] types + --> tests/ui/cfg/packed_sneaky-span-issue-1.rs:5:15 + | +5 | #[hidden_repr(packed)] //~ ERROR may not be used on #[repr(packed)] types + | ^^^^^^ diff --git a/tests/ui/cfg/packed_sneaky-span-issue-2.rs b/tests/ui/cfg/packed_sneaky-span-issue-2.rs new file mode 100644 index 0000000..fcea76b --- /dev/null +++ b/tests/ui/cfg/packed_sneaky-span-issue-2.rs @@ -0,0 +1,15 @@ +use auxiliary_macro::hidden_repr; +use pin_project::pin_project; + +#[pin_project] +#[hidden_repr(packed)] //~ ERROR may not be used on #[repr(packed)] types +struct S { + #[cfg(any())] + #[pin] + f: u32, + #[cfg(not(any()))] + #[pin] + f: u8, +} + +fn main() {} diff --git a/tests/ui/cfg/packed_sneaky-span-issue-2.stderr b/tests/ui/cfg/packed_sneaky-span-issue-2.stderr new file mode 100644 index 0000000..cc2795a --- /dev/null +++ b/tests/ui/cfg/packed_sneaky-span-issue-2.stderr @@ -0,0 +1,5 @@ +error: #[pin_project] attribute may not be used on #[repr(packed)] types + --> tests/ui/cfg/packed_sneaky-span-issue-2.rs:5:15 + | +5 | #[hidden_repr(packed)] //~ ERROR may not be used on #[repr(packed)] types + | ^^^^^^ diff --git a/tests/ui/cfg/packed_sneaky.rs b/tests/ui/cfg/packed_sneaky.rs new file mode 100644 index 0000000..0b01dc9 --- /dev/null +++ b/tests/ui/cfg/packed_sneaky.rs @@ -0,0 +1,12 @@ +use auxiliary_macro::hidden_repr_cfg_not_any; +use pin_project::pin_project; + +// `#[hidden_repr_cfg_not_any(packed)]` generates `#[cfg_attr(not(any()), repr(packed))]`. +#[pin_project] +#[hidden_repr_cfg_not_any(packed)] //~ ERROR may not be used on #[repr(packed)] types +struct S { + #[pin] + f: u32, +} + +fn main() {} diff --git a/tests/ui/cfg/packed_sneaky.stderr b/tests/ui/cfg/packed_sneaky.stderr new file mode 100644 index 0000000..a54c2ec --- /dev/null +++ b/tests/ui/cfg/packed_sneaky.stderr @@ -0,0 +1,5 @@ +error: #[pin_project] attribute may not be used on #[repr(packed)] types + --> tests/ui/cfg/packed_sneaky.rs:6:27 + | +6 | #[hidden_repr_cfg_not_any(packed)] //~ ERROR may not be used on #[repr(packed)] types + | ^^^^^^ diff --git a/tests/ui/cfg/unsupported.rs b/tests/ui/cfg/unsupported.rs new file mode 100644 index 0000000..b950d4b --- /dev/null +++ b/tests/ui/cfg/unsupported.rs @@ -0,0 +1,11 @@ +use pin_project::pin_project; + +#[pin_project] +struct S { + //~^ ERROR may not be used on structs with zero fields + #[cfg(any())] + #[pin] + f: u8, +} + +fn main() {} diff --git a/tests/ui/cfg/unsupported.stderr b/tests/ui/cfg/unsupported.stderr new file mode 100644 index 0000000..e1c871c --- /dev/null +++ b/tests/ui/cfg/unsupported.stderr @@ -0,0 +1,11 @@ +error: #[pin_project] attribute may not be used on structs with zero fields + --> tests/ui/cfg/unsupported.rs:4:10 + | +4 | struct S { + | __________^ +5 | | //~^ ERROR may not be used on structs with zero fields +6 | | #[cfg(any())] +7 | | #[pin] +8 | | f: u8, +9 | | } + | |_^ diff --git a/tests/ui/not_unpin/conflict-unpin.rs b/tests/ui/not_unpin/conflict-unpin.rs new file mode 100644 index 0000000..8985f37 --- /dev/null +++ b/tests/ui/not_unpin/conflict-unpin.rs @@ -0,0 +1,30 @@ +use pin_project::pin_project; + +#[pin_project(!Unpin)] //~ ERROR E0119 +struct Foo { + #[pin] + f1: T, + f2: U, +} + +impl Unpin for Foo where T: Unpin {} + +#[pin_project(!Unpin)] //~ ERROR E0119 +struct Bar { + #[pin] + f1: T, + f2: U, +} + +impl Unpin for Bar {} + +#[pin_project(!Unpin)] //~ ERROR E0119 +struct Baz { + #[pin] + f1: T, + f2: U, +} + +impl Unpin for Baz {} + +fn main() {} diff --git a/tests/ui/not_unpin/conflict-unpin.stderr b/tests/ui/not_unpin/conflict-unpin.stderr new file mode 100644 index 0000000..d79fbfb --- /dev/null +++ b/tests/ui/not_unpin/conflict-unpin.stderr @@ -0,0 +1,26 @@ +error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Foo<_, _>` + --> tests/ui/not_unpin/conflict-unpin.rs:3:15 + | +3 | #[pin_project(!Unpin)] //~ ERROR E0119 + | ^^^^^^ conflicting implementation for `Foo<_, _>` +... +10 | impl Unpin for Foo where T: Unpin {} + | ------------------------------ first implementation here + +error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Bar<_, _>` + --> tests/ui/not_unpin/conflict-unpin.rs:12:15 + | +12 | #[pin_project(!Unpin)] //~ ERROR E0119 + | ^^^^^^ conflicting implementation for `Bar<_, _>` +... +19 | impl Unpin for Bar {} + | ------------------------------ first implementation here + +error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Baz<_, _>` + --> tests/ui/not_unpin/conflict-unpin.rs:21:15 + | +21 | #[pin_project(!Unpin)] //~ ERROR E0119 + | ^^^^^^ conflicting implementation for `Baz<_, _>` +... +28 | impl Unpin for Baz {} + | -------------------------------------------- first implementation here diff --git a/tests/ui/not_unpin/impl-unsafe-unpin.rs b/tests/ui/not_unpin/impl-unsafe-unpin.rs new file mode 100644 index 0000000..2c078c7 --- /dev/null +++ b/tests/ui/not_unpin/impl-unsafe-unpin.rs @@ -0,0 +1,30 @@ +use pin_project::{pin_project, UnsafeUnpin}; + +#[pin_project(!Unpin)] //~ ERROR E0119 +struct Foo { + #[pin] + f1: T, + f2: U, +} + +unsafe impl UnsafeUnpin for Foo where T: Unpin {} + +#[pin_project(!Unpin)] //~ ERROR E0119 +struct Bar { + #[pin] + f1: T, + f2: U, +} + +unsafe impl UnsafeUnpin for Bar {} + +#[pin_project(!Unpin)] //~ ERROR E0119 +struct Baz { + #[pin] + f1: T, + f2: U, +} + +unsafe impl UnsafeUnpin for Baz {} + +fn main() {} diff --git a/tests/ui/not_unpin/impl-unsafe-unpin.stderr b/tests/ui/not_unpin/impl-unsafe-unpin.stderr new file mode 100644 index 0000000..93f225e --- /dev/null +++ b/tests/ui/not_unpin/impl-unsafe-unpin.stderr @@ -0,0 +1,32 @@ +error[E0119]: conflicting implementations of trait `_::_pin_project::UnsafeUnpin` for type `Foo<_, _>` + --> tests/ui/not_unpin/impl-unsafe-unpin.rs:3:1 + | +3 | #[pin_project(!Unpin)] //~ ERROR E0119 + | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Foo<_, _>` +... +10 | unsafe impl UnsafeUnpin for Foo where T: Unpin {} + | ------------------------------------------- first implementation here + | + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0119]: conflicting implementations of trait `_::_pin_project::UnsafeUnpin` for type `Bar<_, _>` + --> tests/ui/not_unpin/impl-unsafe-unpin.rs:12:1 + | +12 | #[pin_project(!Unpin)] //~ ERROR E0119 + | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<_, _>` +... +19 | unsafe impl UnsafeUnpin for Bar {} + | ------------------------------------------- first implementation here + | + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0119]: conflicting implementations of trait `_::_pin_project::UnsafeUnpin` for type `Baz<_, _>` + --> tests/ui/not_unpin/impl-unsafe-unpin.rs:21:1 + | +21 | #[pin_project(!Unpin)] //~ ERROR E0119 + | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Baz<_, _>` +... +28 | unsafe impl UnsafeUnpin for Baz {} + | --------------------------------------------------------- first implementation here + | + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/pin_project/add-attr-to-struct.rs b/tests/ui/pin_project/add-attr-to-struct.rs new file mode 100644 index 0000000..045e796 --- /dev/null +++ b/tests/ui/pin_project/add-attr-to-struct.rs @@ -0,0 +1,20 @@ +use std::marker::PhantomPinned; + +use auxiliary_macro::add_pin_attr; +use pin_project::pin_project; + +#[pin_project] +#[add_pin_attr(struct)] //~ ERROR duplicate #[pin] attribute +struct Foo { + #[pin] + f: PhantomPinned, +} + +#[add_pin_attr(struct)] //~ ERROR #[pin] attribute may only be used on fields of structs or variants +#[pin_project] +struct Bar { + #[pin] + f: PhantomPinned, +} + +fn main() {} diff --git a/tests/ui/pin_project/add-attr-to-struct.stderr b/tests/ui/pin_project/add-attr-to-struct.stderr new file mode 100644 index 0000000..6fb88e8 --- /dev/null +++ b/tests/ui/pin_project/add-attr-to-struct.stderr @@ -0,0 +1,15 @@ +error: duplicate #[pin] attribute + --> tests/ui/pin_project/add-attr-to-struct.rs:7:1 + | +7 | #[add_pin_attr(struct)] //~ ERROR duplicate #[pin] attribute + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `add_pin_attr` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: #[pin] attribute may only be used on fields of structs or variants + --> tests/ui/pin_project/add-attr-to-struct.rs:13:1 + | +13 | #[add_pin_attr(struct)] //~ ERROR #[pin] attribute may only be used on fields of structs or variants + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `add_pin_attr` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/pin_project/add-pinned-field.rs b/tests/ui/pin_project/add-pinned-field.rs new file mode 100644 index 0000000..c415f9c --- /dev/null +++ b/tests/ui/pin_project/add-pinned-field.rs @@ -0,0 +1,23 @@ +use auxiliary_macro::add_pinned_field; +use pin_project::pin_project; + +fn is_unpin() {} + +#[pin_project] +#[add_pinned_field] +struct Foo { + #[pin] + f: u32, +} + +#[add_pinned_field] +#[pin_project] +struct Bar { + #[pin] + f: u32, +} + +fn main() { + is_unpin::(); //~ ERROR E0277 + is_unpin::(); //~ ERROR E0277 +} diff --git a/tests/ui/pin_project/add-pinned-field.stderr b/tests/ui/pin_project/add-pinned-field.stderr new file mode 100644 index 0000000..d0832cc --- /dev/null +++ b/tests/ui/pin_project/add-pinned-field.stderr @@ -0,0 +1,52 @@ +error[E0277]: `PhantomPinned` cannot be unpinned + --> tests/ui/pin_project/add-pinned-field.rs:21:5 + | +21 | is_unpin::(); //~ ERROR E0277 + | ^^^^^^^^^^^^^^^ within `__Foo<'_>`, the trait `Unpin` is not implemented for `PhantomPinned` + | + = note: consider using `Box::pin` +note: required because it appears within the type `__Foo<'_>` + --> tests/ui/pin_project/add-pinned-field.rs:8:8 + | +8 | struct Foo { + | ^^^ +note: required because of the requirements on the impl of `Unpin` for `Foo` + --> tests/ui/pin_project/add-pinned-field.rs:6:1 + | +6 | #[pin_project] + | ^^^^^^^^^^^^^^ +7 | #[add_pinned_field] +8 | struct Foo { + | ^^^ +note: required by a bound in `is_unpin` + --> tests/ui/pin_project/add-pinned-field.rs:4:16 + | +4 | fn is_unpin() {} + | ^^^^^ required by this bound in `is_unpin` + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `PhantomPinned` cannot be unpinned + --> tests/ui/pin_project/add-pinned-field.rs:22:5 + | +22 | is_unpin::(); //~ ERROR E0277 + | ^^^^^^^^^^^^^^^ within `__Bar<'_>`, the trait `Unpin` is not implemented for `PhantomPinned` + | + = note: consider using `Box::pin` +note: required because it appears within the type `__Bar<'_>` + --> tests/ui/pin_project/add-pinned-field.rs:15:8 + | +15 | struct Bar { + | ^^^ +note: required because of the requirements on the impl of `Unpin` for `Bar` + --> tests/ui/pin_project/add-pinned-field.rs:14:1 + | +14 | #[pin_project] + | ^^^^^^^^^^^^^^ +15 | struct Bar { + | ^^^ +note: required by a bound in `is_unpin` + --> tests/ui/pin_project/add-pinned-field.rs:4:16 + | +4 | fn is_unpin() {} + | ^^^^^ required by this bound in `is_unpin` + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/pin_project/conflict-drop.rs b/tests/ui/pin_project/conflict-drop.rs new file mode 100644 index 0000000..4fdb118 --- /dev/null +++ b/tests/ui/pin_project/conflict-drop.rs @@ -0,0 +1,32 @@ +use std::pin::Pin; + +use pin_project::{pin_project, pinned_drop}; + +#[pin_project] //~ ERROR E0119 +struct Foo { + #[pin] + f1: T, + f2: U, +} + +impl Drop for Foo { + fn drop(&mut self) {} +} + +#[pin_project(PinnedDrop)] //~ ERROR E0119 +struct Bar { + #[pin] + f1: T, + f2: U, +} + +#[pinned_drop] +impl PinnedDrop for Bar { + fn drop(self: Pin<&mut Self>) {} +} + +impl Drop for Bar { + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/pin_project/conflict-drop.stderr b/tests/ui/pin_project/conflict-drop.stderr new file mode 100644 index 0000000..4ae628d --- /dev/null +++ b/tests/ui/pin_project/conflict-drop.stderr @@ -0,0 +1,19 @@ +error[E0119]: conflicting implementations of trait `_::FooMustNotImplDrop` for type `Foo<_, _>` + --> tests/ui/pin_project/conflict-drop.rs:5:1 + | +5 | #[pin_project] //~ ERROR E0119 + | ^^^^^^^^^^^^^^ + | | + | first implementation here + | conflicting implementation for `Foo<_, _>` + | + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0119]: conflicting implementations of trait `std::ops::Drop` for type `Bar<_, _>` + --> tests/ui/pin_project/conflict-drop.rs:16:15 + | +16 | #[pin_project(PinnedDrop)] //~ ERROR E0119 + | ^^^^^^^^^^ conflicting implementation for `Bar<_, _>` +... +28 | impl Drop for Bar { + | ----------------------------- first implementation here diff --git a/tests/ui/pin_project/conflict-unpin.rs b/tests/ui/pin_project/conflict-unpin.rs new file mode 100644 index 0000000..f58c45e --- /dev/null +++ b/tests/ui/pin_project/conflict-unpin.rs @@ -0,0 +1,37 @@ +use pin_project::pin_project; + +// The same implementation. + +#[pin_project] //~ ERROR E0119 +struct Foo { + #[pin] + f1: T, + f2: U, +} + +// conflicting implementations +impl Unpin for Foo where T: Unpin {} // Conditional Unpin impl + +// The implementation that under different conditions. + +#[pin_project] //~ ERROR E0119 +struct Bar { + #[pin] + f1: T, + f2: U, +} + +// conflicting implementations +impl Unpin for Bar {} // Non-conditional Unpin impl + +#[pin_project] //~ ERROR E0119 +struct Baz { + #[pin] + f1: T, + f2: U, +} + +// conflicting implementations +impl Unpin for Baz {} // Conditional Unpin impl + +fn main() {} diff --git a/tests/ui/pin_project/conflict-unpin.stderr b/tests/ui/pin_project/conflict-unpin.stderr new file mode 100644 index 0000000..7df5db2 --- /dev/null +++ b/tests/ui/pin_project/conflict-unpin.stderr @@ -0,0 +1,32 @@ +error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Foo<_, _>` + --> tests/ui/pin_project/conflict-unpin.rs:5:1 + | +5 | #[pin_project] //~ ERROR E0119 + | ^^^^^^^^^^^^^^ conflicting implementation for `Foo<_, _>` +... +13 | impl Unpin for Foo where T: Unpin {} // Conditional Unpin impl + | ------------------------------ first implementation here + | + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Bar<_, _>` + --> tests/ui/pin_project/conflict-unpin.rs:17:1 + | +17 | #[pin_project] //~ ERROR E0119 + | ^^^^^^^^^^^^^^ conflicting implementation for `Bar<_, _>` +... +25 | impl Unpin for Bar {} // Non-conditional Unpin impl + | ------------------------------ first implementation here + | + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Baz<_, _>` + --> tests/ui/pin_project/conflict-unpin.rs:27:1 + | +27 | #[pin_project] //~ ERROR E0119 + | ^^^^^^^^^^^^^^ conflicting implementation for `Baz<_, _>` +... +35 | impl Unpin for Baz {} // Conditional Unpin impl + | -------------------------------------------- first implementation here + | + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/pin_project/impl-unsafe-unpin.rs b/tests/ui/pin_project/impl-unsafe-unpin.rs new file mode 100644 index 0000000..562c9b6 --- /dev/null +++ b/tests/ui/pin_project/impl-unsafe-unpin.rs @@ -0,0 +1,30 @@ +use pin_project::{pin_project, UnsafeUnpin}; + +#[pin_project] //~ ERROR E0119 +struct Foo { + #[pin] + f1: T, + f2: U, +} + +unsafe impl UnsafeUnpin for Foo where T: Unpin {} + +#[pin_project] //~ ERROR E0119 +struct Bar { + #[pin] + f1: T, + f2: U, +} + +unsafe impl UnsafeUnpin for Bar {} + +#[pin_project] //~ ERROR E0119 +struct Baz { + #[pin] + f1: T, + f2: U, +} + +unsafe impl UnsafeUnpin for Baz {} + +fn main() {} diff --git a/tests/ui/pin_project/impl-unsafe-unpin.stderr b/tests/ui/pin_project/impl-unsafe-unpin.stderr new file mode 100644 index 0000000..9554b9b --- /dev/null +++ b/tests/ui/pin_project/impl-unsafe-unpin.stderr @@ -0,0 +1,32 @@ +error[E0119]: conflicting implementations of trait `_::_pin_project::UnsafeUnpin` for type `Foo<_, _>` + --> tests/ui/pin_project/impl-unsafe-unpin.rs:3:1 + | +3 | #[pin_project] //~ ERROR E0119 + | ^^^^^^^^^^^^^^ conflicting implementation for `Foo<_, _>` +... +10 | unsafe impl UnsafeUnpin for Foo where T: Unpin {} + | ------------------------------------------- first implementation here + | + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0119]: conflicting implementations of trait `_::_pin_project::UnsafeUnpin` for type `Bar<_, _>` + --> tests/ui/pin_project/impl-unsafe-unpin.rs:12:1 + | +12 | #[pin_project] //~ ERROR E0119 + | ^^^^^^^^^^^^^^ conflicting implementation for `Bar<_, _>` +... +19 | unsafe impl UnsafeUnpin for Bar {} + | ------------------------------------------- first implementation here + | + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0119]: conflicting implementations of trait `_::_pin_project::UnsafeUnpin` for type `Baz<_, _>` + --> tests/ui/pin_project/impl-unsafe-unpin.rs:21:1 + | +21 | #[pin_project] //~ ERROR E0119 + | ^^^^^^^^^^^^^^ conflicting implementation for `Baz<_, _>` +... +28 | unsafe impl UnsafeUnpin for Baz {} + | --------------------------------------------------------- first implementation here + | + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/pin_project/import_unnamed.rs b/tests/ui/pin_project/import_unnamed.rs new file mode 100644 index 0000000..7926e61 --- /dev/null +++ b/tests/ui/pin_project/import_unnamed.rs @@ -0,0 +1,30 @@ +/// Only named projected types can be imported. +/// See visibility.rs for named projected types. + +mod pub_ { + use pin_project::pin_project; + + #[pin_project] + pub struct Default(()); + + #[pin_project(project_replace)] + pub struct Replace(()); +} +#[allow(unused_imports)] +pub mod use_ { + #[rustfmt::skip] + use crate::pub_::__DefaultProjection; //~ ERROR E0432 + #[rustfmt::skip] + use crate::pub_::__DefaultProjectionRef; //~ ERROR E0432 + #[rustfmt::skip] + use crate::pub_::__ReplaceProjection; //~ ERROR E0432 + #[rustfmt::skip] + use crate::pub_::__ReplaceProjectionOwned; //~ ERROR E0432 + #[rustfmt::skip] + use crate::pub_::__ReplaceProjectionRef; //~ ERROR E0432 + + // Confirm that the visibility of the original type is not changed. + pub use crate::pub_::{Default, Replace}; +} + +fn main() {} diff --git a/tests/ui/pin_project/import_unnamed.stderr b/tests/ui/pin_project/import_unnamed.stderr new file mode 100644 index 0000000..260a35a --- /dev/null +++ b/tests/ui/pin_project/import_unnamed.stderr @@ -0,0 +1,29 @@ +error[E0432]: unresolved import `crate::pub_::__DefaultProjection` + --> tests/ui/pin_project/import_unnamed.rs:16:9 + | +16 | use crate::pub_::__DefaultProjection; //~ ERROR E0432 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `__DefaultProjection` in `pub_` + +error[E0432]: unresolved import `crate::pub_::__DefaultProjectionRef` + --> tests/ui/pin_project/import_unnamed.rs:18:9 + | +18 | use crate::pub_::__DefaultProjectionRef; //~ ERROR E0432 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `__DefaultProjectionRef` in `pub_` + +error[E0432]: unresolved import `crate::pub_::__ReplaceProjection` + --> tests/ui/pin_project/import_unnamed.rs:20:9 + | +20 | use crate::pub_::__ReplaceProjection; //~ ERROR E0432 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `__ReplaceProjection` in `pub_` + +error[E0432]: unresolved import `crate::pub_::__ReplaceProjectionOwned` + --> tests/ui/pin_project/import_unnamed.rs:22:9 + | +22 | use crate::pub_::__ReplaceProjectionOwned; //~ ERROR E0432 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `__ReplaceProjectionOwned` in `pub_` + +error[E0432]: unresolved import `crate::pub_::__ReplaceProjectionRef` + --> tests/ui/pin_project/import_unnamed.rs:24:9 + | +24 | use crate::pub_::__ReplaceProjectionRef; //~ ERROR E0432 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `__ReplaceProjectionRef` in `pub_` diff --git a/tests/ui/pin_project/invalid.rs b/tests/ui/pin_project/invalid.rs new file mode 100644 index 0000000..d39a1fd --- /dev/null +++ b/tests/ui/pin_project/invalid.rs @@ -0,0 +1,280 @@ +mod pin_argument { + use pin_project::pin_project; + + #[pin_project] + struct Struct { + #[pin()] //~ ERROR unexpected token + f: (), + } + + #[pin_project] + struct TupleStruct(#[pin(foo)] ()); //~ ERROR unexpected token + + #[pin_project] + enum EnumTuple { + V(#[pin(foo)] ()), //~ ERROR unexpected token + } + + #[pin_project] + enum EnumStruct { + V { + #[pin(foo)] //~ ERROR unexpected token + f: (), + }, + } +} + +mod pin_attribute { + use pin_project::pin_project; + + #[pin_project] + struct DuplicateStruct { + #[pin] + #[pin] //~ ERROR duplicate #[pin] attribute + f: (), + } + + #[pin_project] + struct DuplicateTupleStruct( + #[pin] + #[pin] + (), + //~^^ ERROR duplicate #[pin] attribute + ); + + #[pin_project] + enum DuplicateEnumTuple { + V( + #[pin] + #[pin] + (), + //~^^ ERROR duplicate #[pin] attribute + ), + } + + #[pin_project] + enum DuplicateEnumStruct { + V { + #[pin] + #[pin] //~ ERROR duplicate #[pin] attribute + f: (), + }, + } +} + +mod pin_item { + use pin_project::pin_project; + + #[pin_project] + #[pin] //~ ERROR may only be used on fields of structs or variants + struct Struct { + #[pin] + f: (), + } + + #[pin_project] + enum Variant { + #[pin] //~ ERROR may only be used on fields of structs or variants + V(()), + } + + #[pin_project] + #[pin] //~ ERROR may only be used on fields of structs or variants + enum Enum { + V(()), + } +} + +mod pin_project_argument { + use pin_project::pin_project; + + #[pin_project(Replace)] //~ ERROR `Replace` argument was removed, use `project_replace` argument instead + struct RemovedReplace(#[pin] ()); + + #[pin_project(UnsafeUnpin,,)] //~ ERROR expected identifier + struct Unexpected1(#[pin] ()); + + #[pin_project(Foo)] //~ ERROR unexpected argument + struct Unexpected2(#[pin] ()); + + #[pin_project(,UnsafeUnpin)] //~ ERROR expected identifier + struct Unexpected3(#[pin] ()); + + #[pin_project()] // Ok + struct Unexpected4(#[pin] ()); + + #[pin_project(PinnedDrop PinnedDrop)] //~ ERROR expected `,` + struct Unexpected5(#[pin] ()); + + #[pin_project(PinnedDrop, PinnedDrop)] //~ ERROR duplicate `PinnedDrop` argument + struct DuplicatePinnedDrop(#[pin] ()); + + #[pin_project(UnsafeUnpin, UnsafeUnpin)] //~ ERROR duplicate `UnsafeUnpin` argument + struct DuplicateUnsafeUnpin(#[pin] ()); + + #[pin_project(!Unpin, !Unpin)] //~ ERROR duplicate `!Unpin` argument + struct DuplicateNotUnpin(#[pin] ()); + + #[pin_project(PinnedDrop, UnsafeUnpin, UnsafeUnpin)] //~ ERROR duplicate `UnsafeUnpin` argument + struct Duplicate3(#[pin] ()); + + #[pin_project(PinnedDrop, UnsafeUnpin, PinnedDrop, UnsafeUnpin)] //~ ERROR duplicate `PinnedDrop` argument + struct Duplicate4(#[pin] ()); + + #[pin_project(project = A, project = B)] //~ ERROR duplicate `project` argument + struct DuplicateProject(#[pin] ()); + + #[pin_project(project = A, project_ref = A, project = B)] //~ ERROR duplicate `project` argument + struct DuplicateProject2(#[pin] ()); + + #[pin_project(project_ref = A, project_ref = B)] //~ ERROR duplicate `project_ref` argument + struct DuplicateProjectRef(#[pin] ()); + + #[pin_project(project_replace = A, project_replace = B)] //~ ERROR duplicate `project_replace` argument + struct DuplicateProjectReplace1(#[pin] ()); + + #[pin_project(project_replace, project_replace = B)] //~ ERROR duplicate `project_replace` argument + struct DuplicateProjectReplace2(#[pin] ()); + + #[pin_project(project_replace = A, project_replace)] //~ ERROR duplicate `project_replace` argument + struct DuplicateProjectReplace3(#[pin] ()); + + #[pin_project(project_replace = A)] // Ok + struct ProjectReplaceWithoutReplace(#[pin] ()); + + #[pin_project(PinnedDrop, project_replace)] //~ ERROR arguments `PinnedDrop` and `project_replace` are mutually exclusive + struct PinnedDropWithProjectReplace1(#[pin] ()); + + #[pin_project(project_replace, UnsafeUnpin, PinnedDrop)] //~ ERROR arguments `PinnedDrop` and `project_replace` are mutually exclusive + struct PinnedDropWithProjectReplace2(#[pin] ()); + + #[pin_project(UnsafeUnpin, !Unpin)] //~ ERROR arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive + struct UnsafeUnpinWithNotUnpin1(#[pin] ()); + + #[pin_project(!Unpin, PinnedDrop, UnsafeUnpin)] //~ ERROR arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive + struct UnsafeUnpinWithNotUnpin2(#[pin] ()); + + #[pin_project(!)] //~ ERROR expected `!Unpin`, found `!` + struct NotUnpin1(#[pin] ()); + + #[pin_project(Unpin)] //~ ERROR unexpected argument + struct NotUnpin2(#[pin] ()); + + #[pin_project(project)] //~ ERROR expected `project = `, found `project` + struct Project1(#[pin] ()); + + #[pin_project(project = )] //~ ERROR expected `project = `, found `project =` + struct Project2(#[pin] ()); + + #[pin_project(project = !)] //~ ERROR expected identifier + struct Project3(#[pin] ()); + + #[pin_project(project_ref)] //~ ERROR expected `project_ref = `, found `project_ref` + struct ProjectRef1(#[pin] ()); + + #[pin_project(project_ref = )] //~ ERROR expected `project_ref = `, found `project_ref =` + struct ProjectRef2(#[pin] ()); + + #[pin_project(project_ref = !)] //~ ERROR expected identifier + struct ProjectRef3(#[pin] ()); + + #[pin_project(project_replace)] // Ok + struct ProjectReplace1(#[pin] ()); + + #[pin_project(project_replace = )] //~ ERROR expected `project_replace = `, found `project_replace =` + struct ProjectReplace2(#[pin] ()); + + #[pin_project(project_replace = !)] //~ ERROR expected identifier + struct ProjectReplace3(#[pin] ()); + + #[pin_project(project_replace)] //~ ERROR `project_replace` argument requires a value when used on enums + enum ProjectReplaceEnum { + V(#[pin] ()), + } +} + +mod pin_project_conflict_naming { + use pin_project::pin_project; + + #[pin_project(project = OrigAndProj)] //~ ERROR name `OrigAndProj` is the same as the original type name + struct OrigAndProj(#[pin] ()); + + #[pin_project(project_ref = OrigAndProjRef)] //~ ERROR name `OrigAndProjRef` is the same as the original type name + struct OrigAndProjRef(#[pin] ()); + + #[pin_project(project_replace = OrigAndProjOwn)] //~ ERROR name `OrigAndProjOwn` is the same as the original type name + struct OrigAndProjOwn(#[pin] ()); + + #[pin_project(project = A, project_ref = A)] //~ ERROR name `A` is already specified by `project` argument + struct ProjAndProjRef(#[pin] ()); + + #[pin_project(project = A, project_replace = A)] //~ ERROR name `A` is already specified by `project` argument + struct ProjAndProjOwn(#[pin] ()); + + #[pin_project(project_ref = A, project_replace = A)] //~ ERROR name `A` is already specified by `project_ref` argument + struct ProjRefAndProjOwn(#[pin] ()); +} + +mod pin_project_attribute { + use pin_project::pin_project; + + #[pin_project] + #[pin_project] //~ ERROR duplicate #[pin_project] attribute + struct Duplicate(#[pin] ()); +} + +mod pin_project_item { + use pin_project::pin_project; + + #[pin_project] + struct Struct {} //~ ERROR may not be used on structs with zero fields + + #[pin_project] + struct TupleStruct(); //~ ERROR may not be used on structs with zero fields + + #[pin_project] + struct UnitStruct; //~ ERROR may not be used on structs with zero fields + + #[pin_project] + enum EnumEmpty {} //~ ERROR may not be used on enums without variants + + #[pin_project] + enum EnumDiscriminant { + V = 2, //~ ERROR may not be used on enums with discriminants + } + + #[pin_project] + enum EnumZeroFields { + Unit, //~ ERROR may not be used on enums with zero fields + Tuple(), + Struct {}, + } + + #[pin_project] + union Union { + //~^ ERROR may only be used on structs or enums + f: (), + } + + #[pin_project] + impl Impl {} //~ ERROR may only be used on structs or enums +} + +// #[repr(packed)] is always detected first, even on unsupported structs. +mod pin_project_item_packed { + use pin_project::pin_project; + + #[pin_project] + #[repr(packed)] + struct Struct {} //~ ERROR may not be used on #[repr(packed)] types + + #[pin_project] + #[repr(packed)] + struct TupleStruct(); //~ ERROR may not be used on #[repr(packed)] types + + #[pin_project] + #[repr(packed)] + struct UnitStruct; //~ ERROR may not be used on #[repr(packed)] types +} + +fn main() {} diff --git a/tests/ui/pin_project/invalid.stderr b/tests/ui/pin_project/invalid.stderr new file mode 100644 index 0000000..c43d363 --- /dev/null +++ b/tests/ui/pin_project/invalid.stderr @@ -0,0 +1,364 @@ +error: unexpected token: `()` + --> tests/ui/pin_project/invalid.rs:6:14 + | +6 | #[pin()] //~ ERROR unexpected token + | ^^ + +error: unexpected token: `(foo)` + --> tests/ui/pin_project/invalid.rs:11:29 + | +11 | struct TupleStruct(#[pin(foo)] ()); //~ ERROR unexpected token + | ^^^^^ + +error: unexpected token: `(foo)` + --> tests/ui/pin_project/invalid.rs:15:16 + | +15 | V(#[pin(foo)] ()), //~ ERROR unexpected token + | ^^^^^ + +error: unexpected token: `(foo)` + --> tests/ui/pin_project/invalid.rs:21:18 + | +21 | #[pin(foo)] //~ ERROR unexpected token + | ^^^^^ + +error: duplicate #[pin] attribute + --> tests/ui/pin_project/invalid.rs:33:9 + | +33 | #[pin] //~ ERROR duplicate #[pin] attribute + | ^^^^^^ + +error: duplicate #[pin] attribute + --> tests/ui/pin_project/invalid.rs:40:9 + | +40 | #[pin] + | ^^^^^^ + +error: duplicate #[pin] attribute + --> tests/ui/pin_project/invalid.rs:49:13 + | +49 | #[pin] + | ^^^^^^ + +error: duplicate #[pin] attribute + --> tests/ui/pin_project/invalid.rs:59:13 + | +59 | #[pin] //~ ERROR duplicate #[pin] attribute + | ^^^^^^ + +error: #[pin] attribute may only be used on fields of structs or variants + --> tests/ui/pin_project/invalid.rs:69:5 + | +69 | #[pin] //~ ERROR may only be used on fields of structs or variants + | ^^^^^^ + +error: #[pin] attribute may only be used on fields of structs or variants + --> tests/ui/pin_project/invalid.rs:77:9 + | +77 | #[pin] //~ ERROR may only be used on fields of structs or variants + | ^^^^^^ + +error: #[pin] attribute may only be used on fields of structs or variants + --> tests/ui/pin_project/invalid.rs:82:5 + | +82 | #[pin] //~ ERROR may only be used on fields of structs or variants + | ^^^^^^ + +error: `Replace` argument was removed, use `project_replace` argument instead + --> tests/ui/pin_project/invalid.rs:91:19 + | +91 | #[pin_project(Replace)] //~ ERROR `Replace` argument was removed, use `project_replace` argument instead + | ^^^^^^^ + +error: expected identifier + --> tests/ui/pin_project/invalid.rs:94:31 + | +94 | #[pin_project(UnsafeUnpin,,)] //~ ERROR expected identifier + | ^ + +error: unexpected argument: Foo + --> tests/ui/pin_project/invalid.rs:97:19 + | +97 | #[pin_project(Foo)] //~ ERROR unexpected argument + | ^^^ + +error: expected identifier + --> tests/ui/pin_project/invalid.rs:100:19 + | +100 | #[pin_project(,UnsafeUnpin)] //~ ERROR expected identifier + | ^ + +error: expected `,` + --> tests/ui/pin_project/invalid.rs:106:30 + | +106 | #[pin_project(PinnedDrop PinnedDrop)] //~ ERROR expected `,` + | ^^^^^^^^^^ + +error: duplicate `PinnedDrop` argument + --> tests/ui/pin_project/invalid.rs:109:31 + | +109 | #[pin_project(PinnedDrop, PinnedDrop)] //~ ERROR duplicate `PinnedDrop` argument + | ^^^^^^^^^^ + +error: duplicate `UnsafeUnpin` argument + --> tests/ui/pin_project/invalid.rs:112:32 + | +112 | #[pin_project(UnsafeUnpin, UnsafeUnpin)] //~ ERROR duplicate `UnsafeUnpin` argument + | ^^^^^^^^^^^ + +error: duplicate `!Unpin` argument + --> tests/ui/pin_project/invalid.rs:115:27 + | +115 | #[pin_project(!Unpin, !Unpin)] //~ ERROR duplicate `!Unpin` argument + | ^^^^^^ + +error: duplicate `UnsafeUnpin` argument + --> tests/ui/pin_project/invalid.rs:118:44 + | +118 | #[pin_project(PinnedDrop, UnsafeUnpin, UnsafeUnpin)] //~ ERROR duplicate `UnsafeUnpin` argument + | ^^^^^^^^^^^ + +error: duplicate `PinnedDrop` argument + --> tests/ui/pin_project/invalid.rs:121:44 + | +121 | #[pin_project(PinnedDrop, UnsafeUnpin, PinnedDrop, UnsafeUnpin)] //~ ERROR duplicate `PinnedDrop` argument + | ^^^^^^^^^^ + +error: duplicate `project` argument + --> tests/ui/pin_project/invalid.rs:124:32 + | +124 | #[pin_project(project = A, project = B)] //~ ERROR duplicate `project` argument + | ^^^^^^^^^^^ + +error: duplicate `project` argument + --> tests/ui/pin_project/invalid.rs:127:49 + | +127 | #[pin_project(project = A, project_ref = A, project = B)] //~ ERROR duplicate `project` argument + | ^^^^^^^^^^^ + +error: duplicate `project_ref` argument + --> tests/ui/pin_project/invalid.rs:130:36 + | +130 | #[pin_project(project_ref = A, project_ref = B)] //~ ERROR duplicate `project_ref` argument + | ^^^^^^^^^^^^^^^ + +error: duplicate `project_replace` argument + --> tests/ui/pin_project/invalid.rs:133:40 + | +133 | #[pin_project(project_replace = A, project_replace = B)] //~ ERROR duplicate `project_replace` argument + | ^^^^^^^^^^^^^^^^^^^ + +error: duplicate `project_replace` argument + --> tests/ui/pin_project/invalid.rs:136:36 + | +136 | #[pin_project(project_replace, project_replace = B)] //~ ERROR duplicate `project_replace` argument + | ^^^^^^^^^^^^^^^^^^^ + +error: duplicate `project_replace` argument + --> tests/ui/pin_project/invalid.rs:139:40 + | +139 | #[pin_project(project_replace = A, project_replace)] //~ ERROR duplicate `project_replace` argument + | ^^^^^^^^^^^^^^^ + +error: arguments `PinnedDrop` and `project_replace` are mutually exclusive + --> tests/ui/pin_project/invalid.rs:145:19 + | +145 | #[pin_project(PinnedDrop, project_replace)] //~ ERROR arguments `PinnedDrop` and `project_replace` are mutually exclusive + | ^^^^^^^^^^ + +error: arguments `PinnedDrop` and `project_replace` are mutually exclusive + --> tests/ui/pin_project/invalid.rs:148:49 + | +148 | #[pin_project(project_replace, UnsafeUnpin, PinnedDrop)] //~ ERROR arguments `PinnedDrop` and `project_replace` are mutually exclusive + | ^^^^^^^^^^ + +error: arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive + --> tests/ui/pin_project/invalid.rs:151:19 + | +151 | #[pin_project(UnsafeUnpin, !Unpin)] //~ ERROR arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive + | ^^^^^^^^^^^ + +error: arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive + --> tests/ui/pin_project/invalid.rs:154:39 + | +154 | #[pin_project(!Unpin, PinnedDrop, UnsafeUnpin)] //~ ERROR arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive + | ^^^^^^^^^^^ + +error: expected `!Unpin`, found `!` + --> tests/ui/pin_project/invalid.rs:157:19 + | +157 | #[pin_project(!)] //~ ERROR expected `!Unpin`, found `!` + | ^ + +error: unexpected argument: Unpin + --> tests/ui/pin_project/invalid.rs:160:19 + | +160 | #[pin_project(Unpin)] //~ ERROR unexpected argument + | ^^^^^ + +error: expected `project = `, found `project` + --> tests/ui/pin_project/invalid.rs:163:19 + | +163 | #[pin_project(project)] //~ ERROR expected `project = `, found `project` + | ^^^^^^^ + +error: expected `project = `, found `project =` + --> tests/ui/pin_project/invalid.rs:166:19 + | +166 | #[pin_project(project = )] //~ ERROR expected `project = `, found `project =` + | ^^^^^^^^^ + +error: expected identifier + --> tests/ui/pin_project/invalid.rs:169:29 + | +169 | #[pin_project(project = !)] //~ ERROR expected identifier + | ^ + +error: expected `project_ref = `, found `project_ref` + --> tests/ui/pin_project/invalid.rs:172:19 + | +172 | #[pin_project(project_ref)] //~ ERROR expected `project_ref = `, found `project_ref` + | ^^^^^^^^^^^ + +error: expected `project_ref = `, found `project_ref =` + --> tests/ui/pin_project/invalid.rs:175:19 + | +175 | #[pin_project(project_ref = )] //~ ERROR expected `project_ref = `, found `project_ref =` + | ^^^^^^^^^^^^^ + +error: expected identifier + --> tests/ui/pin_project/invalid.rs:178:33 + | +178 | #[pin_project(project_ref = !)] //~ ERROR expected identifier + | ^ + +error: expected `project_replace = `, found `project_replace =` + --> tests/ui/pin_project/invalid.rs:184:19 + | +184 | #[pin_project(project_replace = )] //~ ERROR expected `project_replace = `, found `project_replace =` + | ^^^^^^^^^^^^^^^^^ + +error: expected identifier + --> tests/ui/pin_project/invalid.rs:187:37 + | +187 | #[pin_project(project_replace = !)] //~ ERROR expected identifier + | ^ + +error: `project_replace` argument requires a value when used on enums + --> tests/ui/pin_project/invalid.rs:190:19 + | +190 | #[pin_project(project_replace)] //~ ERROR `project_replace` argument requires a value when used on enums + | ^^^^^^^^^^^^^^^ + +error: name `OrigAndProj` is the same as the original type name + --> tests/ui/pin_project/invalid.rs:199:29 + | +199 | #[pin_project(project = OrigAndProj)] //~ ERROR name `OrigAndProj` is the same as the original type name + | ^^^^^^^^^^^ + +error: name `OrigAndProjRef` is the same as the original type name + --> tests/ui/pin_project/invalid.rs:202:33 + | +202 | #[pin_project(project_ref = OrigAndProjRef)] //~ ERROR name `OrigAndProjRef` is the same as the original type name + | ^^^^^^^^^^^^^^ + +error: name `OrigAndProjOwn` is the same as the original type name + --> tests/ui/pin_project/invalid.rs:205:37 + | +205 | #[pin_project(project_replace = OrigAndProjOwn)] //~ ERROR name `OrigAndProjOwn` is the same as the original type name + | ^^^^^^^^^^^^^^ + +error: name `A` is already specified by `project` argument + --> tests/ui/pin_project/invalid.rs:208:46 + | +208 | #[pin_project(project = A, project_ref = A)] //~ ERROR name `A` is already specified by `project` argument + | ^ + +error: name `A` is already specified by `project` argument + --> tests/ui/pin_project/invalid.rs:211:50 + | +211 | #[pin_project(project = A, project_replace = A)] //~ ERROR name `A` is already specified by `project` argument + | ^ + +error: name `A` is already specified by `project_ref` argument + --> tests/ui/pin_project/invalid.rs:214:54 + | +214 | #[pin_project(project_ref = A, project_replace = A)] //~ ERROR name `A` is already specified by `project_ref` argument + | ^ + +error: duplicate #[pin_project] attribute + --> tests/ui/pin_project/invalid.rs:222:5 + | +222 | #[pin_project] //~ ERROR duplicate #[pin_project] attribute + | ^^^^^^^^^^^^^^ + +error: #[pin_project] attribute may not be used on structs with zero fields + --> tests/ui/pin_project/invalid.rs:230:19 + | +230 | struct Struct {} //~ ERROR may not be used on structs with zero fields + | ^^ + +error: #[pin_project] attribute may not be used on structs with zero fields + --> tests/ui/pin_project/invalid.rs:233:23 + | +233 | struct TupleStruct(); //~ ERROR may not be used on structs with zero fields + | ^^ + +error: #[pin_project] attribute may not be used on structs with zero fields + --> tests/ui/pin_project/invalid.rs:236:12 + | +236 | struct UnitStruct; //~ ERROR may not be used on structs with zero fields + | ^^^^^^^^^^ + +error: #[pin_project] attribute may not be used on enums without variants + --> tests/ui/pin_project/invalid.rs:239:20 + | +239 | enum EnumEmpty {} //~ ERROR may not be used on enums without variants + | ^^ + +error: #[pin_project] attribute may not be used on enums with discriminants + --> tests/ui/pin_project/invalid.rs:243:13 + | +243 | V = 2, //~ ERROR may not be used on enums with discriminants + | ^ + +error: #[pin_project] attribute may not be used on enums with zero fields + --> tests/ui/pin_project/invalid.rs:248:9 + | +248 | / Unit, //~ ERROR may not be used on enums with zero fields +249 | | Tuple(), +250 | | Struct {}, + | |__________________^ + +error: #[pin_project] attribute may only be used on structs or enums + --> tests/ui/pin_project/invalid.rs:254:5 + | +254 | / union Union { +255 | | //~^ ERROR may only be used on structs or enums +256 | | f: (), +257 | | } + | |_____^ + +error: #[pin_project] attribute may only be used on structs or enums + --> tests/ui/pin_project/invalid.rs:260:5 + | +260 | impl Impl {} //~ ERROR may only be used on structs or enums + | ^^^^^^^^^^^^ + +error: #[pin_project] attribute may not be used on #[repr(packed)] types + --> tests/ui/pin_project/invalid.rs:268:12 + | +268 | #[repr(packed)] + | ^^^^^^ + +error: #[pin_project] attribute may not be used on #[repr(packed)] types + --> tests/ui/pin_project/invalid.rs:272:12 + | +272 | #[repr(packed)] + | ^^^^^^ + +error: #[pin_project] attribute may not be used on #[repr(packed)] types + --> tests/ui/pin_project/invalid.rs:276:12 + | +276 | #[repr(packed)] + | ^^^^^^ diff --git a/tests/ui/pin_project/overlapping_unpin_struct.rs b/tests/ui/pin_project/overlapping_unpin_struct.rs new file mode 100644 index 0000000..abfd5d1 --- /dev/null +++ b/tests/ui/pin_project/overlapping_unpin_struct.rs @@ -0,0 +1,19 @@ +use std::marker::PhantomPinned; + +use pin_project::pin_project; + +#[pin_project] +struct S { + #[pin] + f: T, +} + +struct __S {} + +impl Unpin for __S {} + +fn is_unpin() {} + +fn main() { + is_unpin::>(); //~ ERROR E0277 +} diff --git a/tests/ui/pin_project/overlapping_unpin_struct.stderr b/tests/ui/pin_project/overlapping_unpin_struct.stderr new file mode 100644 index 0000000..1bd200d --- /dev/null +++ b/tests/ui/pin_project/overlapping_unpin_struct.stderr @@ -0,0 +1,25 @@ +error[E0277]: `PhantomPinned` cannot be unpinned + --> tests/ui/pin_project/overlapping_unpin_struct.rs:18:5 + | +18 | is_unpin::>(); //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `_::__S<'_, PhantomPinned>`, the trait `Unpin` is not implemented for `PhantomPinned` + | + = note: consider using `Box::pin` +note: required because it appears within the type `_::__S<'_, PhantomPinned>` + --> tests/ui/pin_project/overlapping_unpin_struct.rs:6:8 + | +6 | struct S { + | ^ +note: required because of the requirements on the impl of `Unpin` for `S` + --> tests/ui/pin_project/overlapping_unpin_struct.rs:5:1 + | +5 | #[pin_project] + | ^^^^^^^^^^^^^^ +6 | struct S { + | ^^^^ +note: required by a bound in `is_unpin` + --> tests/ui/pin_project/overlapping_unpin_struct.rs:15:16 + | +15 | fn is_unpin() {} + | ^^^^^ required by this bound in `is_unpin` + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/pin_project/override-priv-mod.rs b/tests/ui/pin_project/override-priv-mod.rs new file mode 100644 index 0000000..890fd5b --- /dev/null +++ b/tests/ui/pin_project/override-priv-mod.rs @@ -0,0 +1,32 @@ +// https://discord.com/channels/273534239310479360/512792629516173323/870075511009857617 + +extern crate pin_project as pin_project_orig; +extern crate self as pin_project; + +pub use ::pin_project_orig::*; +mod __private { + pub use ::pin_project_orig::__private::*; + pub trait Drop {} +} + +use std::{marker::PhantomPinned, mem}; + +#[pin_project] //~ ERROR conflicting implementations of trait `_::FooMustNotImplDrop` +struct S { + #[pin] + f: (u8, PhantomPinned), +} + +impl Drop for S { + fn drop(&mut self) { + let prev = &self.f.0 as *const _ as usize; + let moved = mem::take(&mut self.f); // move pinned field + let moved = &moved.0 as *const _ as usize; + assert_eq!(prev, moved); // panic + } +} + +fn main() { + let mut x = Box::pin(S { f: (1, PhantomPinned) }); + let _f = x.as_mut().project().f; // first mutable access +} diff --git a/tests/ui/pin_project/override-priv-mod.stderr b/tests/ui/pin_project/override-priv-mod.stderr new file mode 100644 index 0000000..8a3fb9b --- /dev/null +++ b/tests/ui/pin_project/override-priv-mod.stderr @@ -0,0 +1,10 @@ +error[E0119]: conflicting implementations of trait `_::SMustNotImplDrop` for type `S` + --> tests/ui/pin_project/override-priv-mod.rs:14:1 + | +14 | #[pin_project] //~ ERROR conflicting implementations of trait `_::FooMustNotImplDrop` + | ^^^^^^^^^^^^^^ + | | + | first implementation here + | conflicting implementation for `S` + | + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/pin_project/packed-enum.rs b/tests/ui/pin_project/packed-enum.rs new file mode 100644 index 0000000..023c08d --- /dev/null +++ b/tests/ui/pin_project/packed-enum.rs @@ -0,0 +1,24 @@ +use pin_project::pin_project; + +// #[repr(packed)] cannot be apply on enums and will be rejected by rustc. +// However, we should not rely on the behavior of rustc that rejects this. +// https://github.com/taiki-e/pin-project/pull/324#discussion_r612388001 + +#[repr(packed)] //~ ERROR E0517 +enum E1 { + V(()), +} + +#[pin_project] +#[repr(packed)] //~ ERROR E0517 +enum E2 { + V(()), +} + +#[repr(packed)] //~ ERROR E0517 +#[pin_project] +enum E3 { + V(()), +} + +fn main() {} diff --git a/tests/ui/pin_project/packed-enum.stderr b/tests/ui/pin_project/packed-enum.stderr new file mode 100644 index 0000000..1872211 --- /dev/null +++ b/tests/ui/pin_project/packed-enum.stderr @@ -0,0 +1,42 @@ +error: #[repr(packed)] attribute should be applied to a struct or union + --> tests/ui/pin_project/packed-enum.rs:13:8 + | +13 | #[repr(packed)] //~ ERROR E0517 + | ^^^^^^ + +error: #[repr(packed)] attribute should be applied to a struct or union + --> tests/ui/pin_project/packed-enum.rs:18:8 + | +18 | #[repr(packed)] //~ ERROR E0517 + | ^^^^^^ + +error[E0517]: attribute should be applied to a struct or union + --> tests/ui/pin_project/packed-enum.rs:7:8 + | +7 | #[repr(packed)] //~ ERROR E0517 + | ^^^^^^ +8 | / enum E1 { +9 | | V(()), +10 | | } + | |_- not a struct or union + +error[E0517]: attribute should be applied to a struct or union + --> tests/ui/pin_project/packed-enum.rs:13:8 + | +13 | #[repr(packed)] //~ ERROR E0517 + | ^^^^^^ +14 | / enum E2 { +15 | | V(()), +16 | | } + | |_- not a struct or union + +error[E0517]: attribute should be applied to a struct or union + --> tests/ui/pin_project/packed-enum.rs:18:8 + | +18 | #[repr(packed)] //~ ERROR E0517 + | ^^^^^^ +19 | #[pin_project] +20 | / enum E3 { +21 | | V(()), +22 | | } + | |_- not a struct or union diff --git a/tests/ui/pin_project/packed-name-value.rs b/tests/ui/pin_project/packed-name-value.rs new file mode 100644 index 0000000..dedc403 --- /dev/null +++ b/tests/ui/pin_project/packed-name-value.rs @@ -0,0 +1,27 @@ +use pin_project::pin_project; + +// #[repr(packed = "")] is not valid format of #[repr(packed)] and will be +// rejected by rustc. +// However, we should not rely on the behavior of rustc that rejects this. +// https://github.com/taiki-e/pin-project/pull/324#discussion_r612388001 + +// https://github.com/taiki-e/pin-project/pull/324#discussion_r612388001 +// https://github.com/rust-lang/rust/issues/83921 +// #[repr(packed = "")] //~ ERROR E0552 +// struct S1 { +// f: (), +// } + +#[pin_project] +#[repr(packed = "")] //~ ERROR attribute should not be name-value pair +struct S2 { + f: (), +} + +#[repr(packed = "")] //~ ERROR attribute should not be name-value pair +#[pin_project] +struct S3 { + f: (), +} + +fn main() {} diff --git a/tests/ui/pin_project/packed-name-value.stderr b/tests/ui/pin_project/packed-name-value.stderr new file mode 100644 index 0000000..d8b2194 --- /dev/null +++ b/tests/ui/pin_project/packed-name-value.stderr @@ -0,0 +1,23 @@ +error: #[repr(packed)] attribute should not be name-value pair + --> tests/ui/pin_project/packed-name-value.rs:16:8 + | +16 | #[repr(packed = "")] //~ ERROR attribute should not be name-value pair + | ^^^^^^^^^^^ + +error: #[repr(packed)] attribute should not be name-value pair + --> tests/ui/pin_project/packed-name-value.rs:21:8 + | +21 | #[repr(packed = "")] //~ ERROR attribute should not be name-value pair + | ^^^^^^^^^^^ + +error[E0693]: incorrect `repr(packed)` attribute format + --> tests/ui/pin_project/packed-name-value.rs:16:8 + | +16 | #[repr(packed = "")] //~ ERROR attribute should not be name-value pair + | ^^^^^^^^^^^ help: use parentheses instead: `packed()` + +error[E0693]: incorrect `repr(packed)` attribute format + --> tests/ui/pin_project/packed-name-value.rs:21:8 + | +21 | #[repr(packed = "")] //~ ERROR attribute should not be name-value pair + | ^^^^^^^^^^^ help: use parentheses instead: `packed()` diff --git a/tests/ui/pin_project/packed.rs b/tests/ui/pin_project/packed.rs new file mode 100644 index 0000000..dd3ebfd --- /dev/null +++ b/tests/ui/pin_project/packed.rs @@ -0,0 +1,33 @@ +use pin_project::pin_project; + +#[pin_project] +#[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] types +struct Packed1 { + #[pin] + f: u8, +} + +// Test putting 'repr' before the 'pin_project' attribute +#[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] types +#[pin_project] +struct Packed2 { + #[pin] + f: u8, +} + +#[pin_project] +#[repr(packed(2))] //~ ERROR may not be used on #[repr(packed)] types +struct PackedN1 { + #[pin] + f: u32, +} + +// Test putting 'repr' before the 'pin_project' attribute +#[repr(packed(2))] //~ ERROR may not be used on #[repr(packed)] types +#[pin_project] +struct PackedN2 { + #[pin] + f: u32, +} + +fn main() {} diff --git a/tests/ui/pin_project/packed.stderr b/tests/ui/pin_project/packed.stderr new file mode 100644 index 0000000..25ea5f4 --- /dev/null +++ b/tests/ui/pin_project/packed.stderr @@ -0,0 +1,23 @@ +error: #[pin_project] attribute may not be used on #[repr(packed)] types + --> tests/ui/pin_project/packed.rs:4:8 + | +4 | #[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] types + | ^^^^^^ + +error: #[pin_project] attribute may not be used on #[repr(packed)] types + --> tests/ui/pin_project/packed.rs:11:8 + | +11 | #[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] types + | ^^^^^^ + +error: #[pin_project] attribute may not be used on #[repr(packed)] types + --> tests/ui/pin_project/packed.rs:19:8 + | +19 | #[repr(packed(2))] //~ ERROR may not be used on #[repr(packed)] types + | ^^^^^^^^^ + +error: #[pin_project] attribute may not be used on #[repr(packed)] types + --> tests/ui/pin_project/packed.rs:26:8 + | +26 | #[repr(packed(2))] //~ ERROR may not be used on #[repr(packed)] types + | ^^^^^^^^^ diff --git a/tests/ui/pin_project/packed_sneaky-1.rs b/tests/ui/pin_project/packed_sneaky-1.rs new file mode 100644 index 0000000..83a4612 --- /dev/null +++ b/tests/ui/pin_project/packed_sneaky-1.rs @@ -0,0 +1,41 @@ +use std::pin::Pin; + +use auxiliary_macro::{hidden_repr, hidden_repr2}; +use pin_project::{pin_project, pinned_drop, UnsafeUnpin}; + +#[pin_project] //~ ERROR may not be used on #[repr(packed)] types +#[hidden_repr(packed)] +struct A { + #[pin] + f: u32, +} + +#[hidden_repr2] +#[pin_project] //~ ERROR may not be used on #[repr(packed)] types +struct B { + #[pin] + f: u32, +} + +#[pin_project(UnsafeUnpin)] //~ ERROR may not be used on #[repr(packed)] types +#[hidden_repr(packed)] +struct C { + #[pin] + f: u32, +} + +unsafe impl UnsafeUnpin for C {} + +#[pin_project(PinnedDrop)] //~ ERROR may not be used on #[repr(packed)] types +#[hidden_repr(packed)] +struct D { + #[pin] + f: u32, +} + +#[pinned_drop] +impl PinnedDrop for D { + fn drop(self: Pin<&mut Self>) {} +} + +fn main() {} diff --git a/tests/ui/pin_project/packed_sneaky-1.stderr b/tests/ui/pin_project/packed_sneaky-1.stderr new file mode 100644 index 0000000..0746e1a --- /dev/null +++ b/tests/ui/pin_project/packed_sneaky-1.stderr @@ -0,0 +1,25 @@ +error: #[pin_project] attribute may not be used on #[repr(packed)] types + --> tests/ui/pin_project/packed_sneaky-1.rs:7:15 + | +7 | #[hidden_repr(packed)] + | ^^^^^^ + +error: #[pin_project] attribute may not be used on #[repr(packed)] types + --> tests/ui/pin_project/packed_sneaky-1.rs:13:1 + | +13 | #[hidden_repr2] + | ^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `hidden_repr2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: #[pin_project] attribute may not be used on #[repr(packed)] types + --> tests/ui/pin_project/packed_sneaky-1.rs:21:15 + | +21 | #[hidden_repr(packed)] + | ^^^^^^ + +error: #[pin_project] attribute may not be used on #[repr(packed)] types + --> tests/ui/pin_project/packed_sneaky-1.rs:30:15 + | +30 | #[hidden_repr(packed)] + | ^^^^^^ diff --git a/tests/ui/pin_project/packed_sneaky-2.rs b/tests/ui/pin_project/packed_sneaky-2.rs new file mode 100644 index 0000000..b098358 --- /dev/null +++ b/tests/ui/pin_project/packed_sneaky-2.rs @@ -0,0 +1,12 @@ +use auxiliary_macro::hidden_repr_macro; +use pin_project::pin_project; + +hidden_repr_macro! { //~ ERROR may not be used on #[repr(packed)] types + #[pin_project] + struct B { + #[pin] + f: u32, + } +} + +fn main() {} diff --git a/tests/ui/pin_project/packed_sneaky-2.stderr b/tests/ui/pin_project/packed_sneaky-2.stderr new file mode 100644 index 0000000..d643052 --- /dev/null +++ b/tests/ui/pin_project/packed_sneaky-2.stderr @@ -0,0 +1,13 @@ +error: #[pin_project] attribute may not be used on #[repr(packed)] types + --> tests/ui/pin_project/packed_sneaky-2.rs:4:1 + | +4 | / hidden_repr_macro! { //~ ERROR may not be used on #[repr(packed)] types +5 | | #[pin_project] +6 | | struct B { +7 | | #[pin] +8 | | f: u32, +9 | | } +10 | | } + | |_^ + | + = note: this error originates in the macro `hidden_repr_macro` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/pin_project/packed_sneaky-3.rs b/tests/ui/pin_project/packed_sneaky-3.rs new file mode 100644 index 0000000..d3f00f3 --- /dev/null +++ b/tests/ui/pin_project/packed_sneaky-3.rs @@ -0,0 +1,32 @@ +use auxiliary_macro::{hidden_repr_macro, HiddenRepr}; +use pin_project::pin_project; + +hidden_repr_macro! {} //~ ERROR expected item after attributes +#[pin_project] +struct S1 { + #[pin] + f: u32, +} + +macro_rules! hidden_repr_macro2 { + () => { + #[repr(packed)] //~ ERROR expected item after attributes + }; +} + +hidden_repr_macro2! {} +#[pin_project] +struct S2 { + #[pin] + f: u32, +} + +#[derive(HiddenRepr)] //~ ERROR expected item after attributes +struct S3 {} +#[pin_project] +struct S4 { + #[pin] + f: u32, +} + +fn main() {} diff --git a/tests/ui/pin_project/packed_sneaky-3.stderr b/tests/ui/pin_project/packed_sneaky-3.stderr new file mode 100644 index 0000000..c97f18b --- /dev/null +++ b/tests/ui/pin_project/packed_sneaky-3.stderr @@ -0,0 +1,32 @@ +error: expected item after attributes + --> tests/ui/pin_project/packed_sneaky-3.rs:4:1 + | +4 | hidden_repr_macro! {} //~ ERROR expected item after attributes + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `hidden_repr_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected item after attributes + --> tests/ui/pin_project/packed_sneaky-3.rs:13:9 + | +13 | #[repr(packed)] //~ ERROR expected item after attributes + | ^^^^^^^^^^^^^^^ +... +17 | hidden_repr_macro2! {} + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `hidden_repr_macro2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected item after attributes + --> tests/ui/pin_project/packed_sneaky-3.rs:24:10 + | +24 | #[derive(HiddenRepr)] //~ ERROR expected item after attributes + | ^^^^^^^^^^ + | + = note: this error originates in the derive macro `HiddenRepr` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: proc-macro derive produced unparseable tokens + --> tests/ui/pin_project/packed_sneaky-3.rs:24:10 + | +24 | #[derive(HiddenRepr)] //~ ERROR expected item after attributes + | ^^^^^^^^^^ diff --git a/tests/ui/pin_project/packed_sneaky-4.rs b/tests/ui/pin_project/packed_sneaky-4.rs new file mode 100644 index 0000000..fb954ba --- /dev/null +++ b/tests/ui/pin_project/packed_sneaky-4.rs @@ -0,0 +1,15 @@ +// https://github.com/taiki-e/pin-project/issues/342 + +#![allow(unaligned_references)] + +use auxiliary_macro::hidden_repr2; +use pin_project::pin_project; + +#[pin_project] //~ ERROR reference to packed field is unaligned +#[hidden_repr2] +struct A { + #[pin] + f: u32, +} + +fn main() {} diff --git a/tests/ui/pin_project/packed_sneaky-4.stderr b/tests/ui/pin_project/packed_sneaky-4.stderr new file mode 100644 index 0000000..8072ce2 --- /dev/null +++ b/tests/ui/pin_project/packed_sneaky-4.stderr @@ -0,0 +1,16 @@ +error: reference to packed field is unaligned + --> tests/ui/pin_project/packed_sneaky-4.rs:8:1 + | +8 | #[pin_project] //~ ERROR reference to packed field is unaligned + | ^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui/pin_project/packed_sneaky-4.rs:8:1 + | +8 | #[pin_project] //~ ERROR reference to packed field is unaligned + | ^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/pin_project/private_in_public-enum.rs b/tests/ui/pin_project/private_in_public-enum.rs new file mode 100644 index 0000000..15a82a9 --- /dev/null +++ b/tests/ui/pin_project/private_in_public-enum.rs @@ -0,0 +1,23 @@ +// Even if allows private_in_public, these are errors. + +#![allow(private_in_public)] + +pub enum PublicEnum { + V(PrivateEnum), //~ ERROR E0446 +} + +enum PrivateEnum { + V(u8), +} + +mod foo { + pub(crate) enum CrateEnum { + V(PrivateEnum), //~ ERROR E0446 + } + + enum PrivateEnum { + V(u8), + } +} + +fn main() {} diff --git a/tests/ui/pin_project/private_in_public-enum.stderr b/tests/ui/pin_project/private_in_public-enum.stderr new file mode 100644 index 0000000..c93b265 --- /dev/null +++ b/tests/ui/pin_project/private_in_public-enum.stderr @@ -0,0 +1,17 @@ +error[E0446]: private type `PrivateEnum` in public interface + --> tests/ui/pin_project/private_in_public-enum.rs:6:7 + | +6 | V(PrivateEnum), //~ ERROR E0446 + | ^^^^^^^^^^^ can't leak private type +... +9 | enum PrivateEnum { + | ---------------- `PrivateEnum` declared as private + +error[E0446]: private type `foo::PrivateEnum` in public interface + --> tests/ui/pin_project/private_in_public-enum.rs:15:11 + | +15 | V(PrivateEnum), //~ ERROR E0446 + | ^^^^^^^^^^^ can't leak private type +... +18 | enum PrivateEnum { + | ---------------- `foo::PrivateEnum` declared as private diff --git a/tests/ui/pin_project/project_replace_unsized.rs b/tests/ui/pin_project/project_replace_unsized.rs new file mode 100644 index 0000000..20dde12 --- /dev/null +++ b/tests/ui/pin_project/project_replace_unsized.rs @@ -0,0 +1,11 @@ +use pin_project::pin_project; + +#[pin_project(project_replace)] //~ ERROR E0277 +struct Struct { + f: T, +} + +#[pin_project(project_replace)] //~ ERROR E0277 +struct TupleStruct(T); + +fn main() {} diff --git a/tests/ui/pin_project/project_replace_unsized.stderr b/tests/ui/pin_project/project_replace_unsized.stderr new file mode 100644 index 0000000..042b499 --- /dev/null +++ b/tests/ui/pin_project/project_replace_unsized.stderr @@ -0,0 +1,118 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> tests/ui/pin_project/project_replace_unsized.rs:3:15 + | +3 | #[pin_project(project_replace)] //~ ERROR E0277 + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time +4 | struct Struct { + | - this type parameter needs to be `std::marker::Sized` + | +note: required because it appears within the type `Struct` + --> tests/ui/pin_project/project_replace_unsized.rs:4:8 + | +4 | struct Struct { + | ^^^^^^ + = help: unsized fn params are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +4 - struct Struct { +4 + struct Struct { + | +help: function arguments must have a statically known size, borrowed types always have a known size + | +3 | #[pin_project(&project_replace)] //~ ERROR E0277 + | + + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> tests/ui/pin_project/project_replace_unsized.rs:3:1 + | +3 | #[pin_project(project_replace)] //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time +4 | struct Struct { + | - this type parameter needs to be `std::marker::Sized` + | +note: required because it appears within the type `Struct` + --> tests/ui/pin_project/project_replace_unsized.rs:4:8 + | +4 | struct Struct { + | ^^^^^^ +note: required by a bound in `UnsafeOverwriteGuard::::new` + --> src/lib.rs + | + | impl UnsafeOverwriteGuard { + | ^ required by this bound in `UnsafeOverwriteGuard::::new` + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +4 - struct Struct { +4 + struct Struct { + | + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> tests/ui/pin_project/project_replace_unsized.rs:5:5 + | +3 | #[pin_project(project_replace)] //~ ERROR E0277 + | ------------------------------- required by a bound introduced by this call +4 | struct Struct { + | - this type parameter needs to be `std::marker::Sized` +5 | f: T, + | ^ doesn't have a size known at compile-time + | +note: required by a bound in `std::ptr::read` + --> $RUST/core/src/ptr/mod.rs + | + | pub const unsafe fn read(src: *const T) -> T { + | ^ required by this bound in `std::ptr::read` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +4 - struct Struct { +4 + struct Struct { + | + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> tests/ui/pin_project/project_replace_unsized.rs:8:15 + | +8 | #[pin_project(project_replace)] //~ ERROR E0277 + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time +9 | struct TupleStruct(T); + | - this type parameter needs to be `std::marker::Sized` + | +note: required because it appears within the type `TupleStruct` + --> tests/ui/pin_project/project_replace_unsized.rs:9:8 + | +9 | struct TupleStruct(T); + | ^^^^^^^^^^^ + = help: unsized fn params are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +9 - struct TupleStruct(T); +9 + struct TupleStruct(T); + | +help: function arguments must have a statically known size, borrowed types always have a known size + | +8 | #[pin_project(&project_replace)] //~ ERROR E0277 + | + + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> tests/ui/pin_project/project_replace_unsized.rs:8:1 + | +8 | #[pin_project(project_replace)] //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time +9 | struct TupleStruct(T); + | - this type parameter needs to be `std::marker::Sized` + | +note: required because it appears within the type `TupleStruct` + --> tests/ui/pin_project/project_replace_unsized.rs:9:8 + | +9 | struct TupleStruct(T); + | ^^^^^^^^^^^ +note: required by a bound in `UnsafeOverwriteGuard::::new` + --> src/lib.rs + | + | impl UnsafeOverwriteGuard { + | ^ required by this bound in `UnsafeOverwriteGuard::::new` + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +9 - struct TupleStruct(T); +9 + struct TupleStruct(T); + | diff --git a/tests/ui/pin_project/project_replace_unsized_fn_params.rs b/tests/ui/pin_project/project_replace_unsized_fn_params.rs new file mode 100644 index 0000000..e0fa25b --- /dev/null +++ b/tests/ui/pin_project/project_replace_unsized_fn_params.rs @@ -0,0 +1,13 @@ +#![feature(unsized_fn_params)] + +use pin_project::pin_project; + +#[pin_project(project_replace)] //~ ERROR E0277 +struct Struct { + f: T, +} + +#[pin_project(project_replace)] //~ ERROR E0277 +struct TupleStruct(T); + +fn main() {} diff --git a/tests/ui/pin_project/project_replace_unsized_fn_params.stderr b/tests/ui/pin_project/project_replace_unsized_fn_params.stderr new file mode 100644 index 0000000..10fad08 --- /dev/null +++ b/tests/ui/pin_project/project_replace_unsized_fn_params.stderr @@ -0,0 +1,112 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:6:8 + | +6 | struct Struct { + | ^^^^^^^-^^^^^^^^^ + | | | + | | this type parameter needs to be `std::marker::Sized` + | doesn't have a size known at compile-time + | +note: required because it appears within the type `__StructProjectionOwned` + --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:6:8 + | +6 | struct Struct { + | ^^^^^^ + = note: the return type of a function must have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +6 - struct Struct { +6 + struct Struct { + | + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:5:1 + | +5 | #[pin_project(project_replace)] //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time +6 | struct Struct { + | - this type parameter needs to be `std::marker::Sized` + | +note: required because it appears within the type `Struct` + --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:6:8 + | +6 | struct Struct { + | ^^^^^^ +note: required by a bound in `UnsafeOverwriteGuard::::new` + --> src/lib.rs + | + | impl UnsafeOverwriteGuard { + | ^ required by this bound in `UnsafeOverwriteGuard::::new` + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +6 - struct Struct { +6 + struct Struct { + | + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:7:5 + | +5 | #[pin_project(project_replace)] //~ ERROR E0277 + | ------------------------------- required by a bound introduced by this call +6 | struct Struct { + | - this type parameter needs to be `std::marker::Sized` +7 | f: T, + | ^ doesn't have a size known at compile-time + | +note: required by a bound in `std::ptr::read` + --> $RUST/core/src/ptr/mod.rs + | + | pub const unsafe fn read(src: *const T) -> T { + | ^ required by this bound in `std::ptr::read` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +6 - struct Struct { +6 + struct Struct { + | + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:11:8 + | +11 | struct TupleStruct(T); + | ^^^^^^^^^^^^-^^^^^^^^^ + | | | + | | this type parameter needs to be `std::marker::Sized` + | doesn't have a size known at compile-time + | +note: required because it appears within the type `__TupleStructProjectionOwned` + --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:11:8 + | +11 | struct TupleStruct(T); + | ^^^^^^^^^^^ + = note: the return type of a function must have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +11 - struct TupleStruct(T); +11 + struct TupleStruct(T); + | + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:10:1 + | +10 | #[pin_project(project_replace)] //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time +11 | struct TupleStruct(T); + | - this type parameter needs to be `std::marker::Sized` + | +note: required because it appears within the type `TupleStruct` + --> tests/ui/pin_project/project_replace_unsized_fn_params.rs:11:8 + | +11 | struct TupleStruct(T); + | ^^^^^^^^^^^ +note: required by a bound in `UnsafeOverwriteGuard::::new` + --> src/lib.rs + | + | impl UnsafeOverwriteGuard { + | ^ required by this bound in `UnsafeOverwriteGuard::::new` + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +11 - struct TupleStruct(T); +11 + struct TupleStruct(T); + | diff --git a/tests/ui/pin_project/remove-attr-from-field.rs b/tests/ui/pin_project/remove-attr-from-field.rs new file mode 100644 index 0000000..fd14da3 --- /dev/null +++ b/tests/ui/pin_project/remove-attr-from-field.rs @@ -0,0 +1,33 @@ +use std::{marker::PhantomPinned, pin::Pin}; + +use auxiliary_macro::remove_attr; +use pin_project::pin_project; + +fn is_unpin() {} + +#[pin_project] +#[remove_attr(field_all)] +struct A { + #[pin] + f: PhantomPinned, +} + +#[remove_attr(field_all)] +#[pin_project] +struct B { + #[pin] + f: PhantomPinned, +} + +fn main() { + is_unpin::(); + is_unpin::(); + + let mut x = A { f: PhantomPinned }; + let x = Pin::new(&mut x).project(); + let _: Pin<&mut PhantomPinned> = x.f; //~ ERROR E0308 + + let mut x = B { f: PhantomPinned }; + let x = Pin::new(&mut x).project(); + let _: Pin<&mut PhantomPinned> = x.f; //~ ERROR E0308 +} diff --git a/tests/ui/pin_project/remove-attr-from-field.stderr b/tests/ui/pin_project/remove-attr-from-field.stderr new file mode 100644 index 0000000..697cd63 --- /dev/null +++ b/tests/ui/pin_project/remove-attr-from-field.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> tests/ui/pin_project/remove-attr-from-field.rs:28:38 + | +28 | let _: Pin<&mut PhantomPinned> = x.f; //~ ERROR E0308 + | ----------------------- ^^^ expected struct `Pin`, found `&mut PhantomPinned` + | | + | expected due to this + | + = note: expected struct `Pin<&mut PhantomPinned>` + found mutable reference `&mut PhantomPinned` + +error[E0308]: mismatched types + --> tests/ui/pin_project/remove-attr-from-field.rs:32:38 + | +32 | let _: Pin<&mut PhantomPinned> = x.f; //~ ERROR E0308 + | ----------------------- ^^^ expected struct `Pin`, found `&mut PhantomPinned` + | | + | expected due to this + | + = note: expected struct `Pin<&mut PhantomPinned>` + found mutable reference `&mut PhantomPinned` diff --git a/tests/ui/pin_project/remove-attr-from-struct.rs b/tests/ui/pin_project/remove-attr-from-struct.rs new file mode 100644 index 0000000..cbe5aba --- /dev/null +++ b/tests/ui/pin_project/remove-attr-from-struct.rs @@ -0,0 +1,47 @@ +use std::{marker::PhantomPinned, pin::Pin}; + +use auxiliary_macro::remove_attr; +use pin_project::pin_project; + +fn is_unpin() {} + +#[pin_project] +#[remove_attr(struct_all)] +struct A { + #[pin] //~ ERROR cannot find attribute `pin` in this scope + f: PhantomPinned, +} + +#[remove_attr(struct_all)] +#[pin_project] +struct B { + #[pin] //~ ERROR cannot find attribute `pin` in this scope + f: PhantomPinned, +} + +#[pin_project] //~ ERROR has been removed +#[remove_attr(struct_pin)] +struct C { + f: PhantomPinned, +} + +#[remove_attr(struct_pin)] +#[pin_project] // Ok +struct D { + f: PhantomPinned, +} + +fn main() { + is_unpin::(); //~ ERROR E0277 + is_unpin::(); //~ ERROR E0277 + is_unpin::(); // Ok + + let mut x = A { f: PhantomPinned }; + let _ = Pin::new(&mut x).project(); //~ ERROR E0277,E0599 + + let mut x = B { f: PhantomPinned }; + let _ = Pin::new(&mut x).project(); //~ ERROR E0277,E0599 + + let mut x = D { f: PhantomPinned }; + let _ = Pin::new(&mut x).project(); //~ Ok +} diff --git a/tests/ui/pin_project/remove-attr-from-struct.stderr b/tests/ui/pin_project/remove-attr-from-struct.stderr new file mode 100644 index 0000000..1a9cd42 --- /dev/null +++ b/tests/ui/pin_project/remove-attr-from-struct.stderr @@ -0,0 +1,107 @@ +error: #[pin_project] attribute has been removed + --> tests/ui/pin_project/remove-attr-from-struct.rs:22:1 + | +22 | #[pin_project] //~ ERROR has been removed + | ^^^^^^^^^^^^^^ + | + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot find attribute `pin` in this scope + --> tests/ui/pin_project/remove-attr-from-struct.rs:18:7 + | +18 | #[pin] //~ ERROR cannot find attribute `pin` in this scope + | ^^^ + +error: cannot find attribute `pin` in this scope + --> tests/ui/pin_project/remove-attr-from-struct.rs:11:7 + | +11 | #[pin] //~ ERROR cannot find attribute `pin` in this scope + | ^^^ + +error[E0277]: `PhantomPinned` cannot be unpinned + --> tests/ui/pin_project/remove-attr-from-struct.rs:35:5 + | +35 | is_unpin::(); //~ ERROR E0277 + | ^^^^^^^^^^^^^ within `A`, the trait `Unpin` is not implemented for `PhantomPinned` + | + = note: consider using `Box::pin` +note: required because it appears within the type `A` + --> tests/ui/pin_project/remove-attr-from-struct.rs:10:8 + | +10 | struct A { + | ^ +note: required by a bound in `is_unpin` + --> tests/ui/pin_project/remove-attr-from-struct.rs:6:16 + | +6 | fn is_unpin() {} + | ^^^^^ required by this bound in `is_unpin` + +error[E0277]: `PhantomPinned` cannot be unpinned + --> tests/ui/pin_project/remove-attr-from-struct.rs:36:5 + | +36 | is_unpin::(); //~ ERROR E0277 + | ^^^^^^^^^^^^^ within `B`, the trait `Unpin` is not implemented for `PhantomPinned` + | + = note: consider using `Box::pin` +note: required because it appears within the type `B` + --> tests/ui/pin_project/remove-attr-from-struct.rs:17:8 + | +17 | struct B { + | ^ +note: required by a bound in `is_unpin` + --> tests/ui/pin_project/remove-attr-from-struct.rs:6:16 + | +6 | fn is_unpin() {} + | ^^^^^ required by this bound in `is_unpin` + +error[E0277]: `PhantomPinned` cannot be unpinned + --> tests/ui/pin_project/remove-attr-from-struct.rs:40:22 + | +40 | let _ = Pin::new(&mut x).project(); //~ ERROR E0277,E0599 + | -------- ^^^^^^ within `A`, the trait `Unpin` is not implemented for `PhantomPinned` + | | + | required by a bound introduced by this call + | + = note: consider using `Box::pin` +note: required because it appears within the type `A` + --> tests/ui/pin_project/remove-attr-from-struct.rs:10:8 + | +10 | struct A { + | ^ +note: required by a bound in `Pin::

::new` + --> $RUST/core/src/pin.rs + | + | impl> Pin

{ + | ^^^^^ required by this bound in `Pin::

::new` + +error[E0599]: no method named `project` found for struct `Pin<&mut A>` in the current scope + --> tests/ui/pin_project/remove-attr-from-struct.rs:40:30 + | +40 | let _ = Pin::new(&mut x).project(); //~ ERROR E0277,E0599 + | ^^^^^^^ method not found in `Pin<&mut A>` + +error[E0277]: `PhantomPinned` cannot be unpinned + --> tests/ui/pin_project/remove-attr-from-struct.rs:43:22 + | +43 | let _ = Pin::new(&mut x).project(); //~ ERROR E0277,E0599 + | -------- ^^^^^^ within `B`, the trait `Unpin` is not implemented for `PhantomPinned` + | | + | required by a bound introduced by this call + | + = note: consider using `Box::pin` +note: required because it appears within the type `B` + --> tests/ui/pin_project/remove-attr-from-struct.rs:17:8 + | +17 | struct B { + | ^ +note: required by a bound in `Pin::

::new` + --> $RUST/core/src/pin.rs + | + | impl> Pin

{ + | ^^^^^ required by this bound in `Pin::

::new` + +error[E0599]: no method named `project` found for struct `Pin<&mut B>` in the current scope + --> tests/ui/pin_project/remove-attr-from-struct.rs:43:30 + | +43 | let _ = Pin::new(&mut x).project(); //~ ERROR E0277,E0599 + | ^^^^^^^ method not found in `Pin<&mut B>` diff --git a/tests/ui/pin_project/safe_packed_borrows.rs b/tests/ui/pin_project/safe_packed_borrows.rs new file mode 100644 index 0000000..de8181c --- /dev/null +++ b/tests/ui/pin_project/safe_packed_borrows.rs @@ -0,0 +1,26 @@ +#![deny(renamed_and_removed_lints)] +#![deny(safe_packed_borrows)] //~ ERROR has been renamed to `unaligned_references` +#![allow(unaligned_references)] + +// This lint was removed in https://github.com/rust-lang/rust/pull/82525 (nightly-2021-03-28). +// Refs: +// - https://github.com/rust-lang/rust/pull/82525 +// - https://github.com/rust-lang/rust/issues/46043 + +#[repr(packed)] +struct Packed { + f: u32, +} + +#[repr(packed(2))] +struct PackedN { + f: u32, +} + +fn main() { + let a = Packed { f: 1 }; + let _ = &a.f; + + let b = PackedN { f: 1 }; + let _ = &b.f; +} diff --git a/tests/ui/pin_project/safe_packed_borrows.stderr b/tests/ui/pin_project/safe_packed_borrows.stderr new file mode 100644 index 0000000..f483b6d --- /dev/null +++ b/tests/ui/pin_project/safe_packed_borrows.stderr @@ -0,0 +1,11 @@ +error: lint `safe_packed_borrows` has been renamed to `unaligned_references` + --> tests/ui/pin_project/safe_packed_borrows.rs:2:9 + | +2 | #![deny(safe_packed_borrows)] //~ ERROR has been renamed to `unaligned_references` + | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `unaligned_references` + | +note: the lint level is defined here + --> tests/ui/pin_project/safe_packed_borrows.rs:1:9 + | +1 | #![deny(renamed_and_removed_lints)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/pin_project/unaligned_references.rs b/tests/ui/pin_project/unaligned_references.rs new file mode 100644 index 0000000..eaf185d --- /dev/null +++ b/tests/ui/pin_project/unaligned_references.rs @@ -0,0 +1,21 @@ +#![forbid(unaligned_references)] + +// Refs: https://github.com/rust-lang/rust/issues/82523 + +#[repr(packed)] +struct Packed { + f: u32, +} + +#[repr(packed(2))] +struct PackedN { + f: u32, +} + +fn main() { + let a = Packed { f: 1 }; + let _ = &a.f; //~ ERROR reference to packed field is unaligned + + let b = PackedN { f: 1 }; + let _ = &b.f; //~ ERROR reference to packed field is unaligned +} diff --git a/tests/ui/pin_project/unaligned_references.stderr b/tests/ui/pin_project/unaligned_references.stderr new file mode 100644 index 0000000..8d5ddfc --- /dev/null +++ b/tests/ui/pin_project/unaligned_references.stderr @@ -0,0 +1,26 @@ +error: reference to packed field is unaligned + --> tests/ui/pin_project/unaligned_references.rs:17:13 + | +17 | let _ = &a.f; //~ ERROR reference to packed field is unaligned + | ^^^^ + | +note: the lint level is defined here + --> tests/ui/pin_project/unaligned_references.rs:1:11 + | +1 | #![forbid(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> tests/ui/pin_project/unaligned_references.rs:20:13 + | +20 | let _ = &b.f; //~ ERROR reference to packed field is unaligned + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) diff --git a/tests/ui/pin_project/unpin_sneaky.rs b/tests/ui/pin_project/unpin_sneaky.rs new file mode 100644 index 0000000..3f5f32b --- /dev/null +++ b/tests/ui/pin_project/unpin_sneaky.rs @@ -0,0 +1,11 @@ +use pin_project::pin_project; + +#[pin_project] +struct S { + #[pin] + f: u8, +} + +impl Unpin for __S {} //~ ERROR E0412,E0321 + +fn main() {} diff --git a/tests/ui/pin_project/unpin_sneaky.stderr b/tests/ui/pin_project/unpin_sneaky.stderr new file mode 100644 index 0000000..82c2aa5 --- /dev/null +++ b/tests/ui/pin_project/unpin_sneaky.stderr @@ -0,0 +1,5 @@ +error[E0412]: cannot find type `__S` in this scope + --> tests/ui/pin_project/unpin_sneaky.rs:9:16 + | +9 | impl Unpin for __S {} //~ ERROR E0412,E0321 + | ^^^ not found in this scope diff --git a/tests/ui/pin_project/visibility.rs b/tests/ui/pin_project/visibility.rs new file mode 100644 index 0000000..fdff5a6 --- /dev/null +++ b/tests/ui/pin_project/visibility.rs @@ -0,0 +1,49 @@ +/// Only named projected types can be imported. +/// See import_unnamed.rs for unnamed projected types. + +mod pub_ { + use pin_project::pin_project; + + #[pin_project(project = DProj, project_ref = DProjRef)] + pub struct Default(()); + + #[pin_project(project = RProj, project_ref = RProjRef, project_replace = RProjOwn)] + pub struct Replace(()); +} +pub mod pub_use { + #[rustfmt::skip] + pub use crate::pub_::DProj; //~ ERROR E0365 + #[rustfmt::skip] + pub use crate::pub_::DProjRef; //~ ERROR E0365 + #[rustfmt::skip] + pub use crate::pub_::RProj; //~ ERROR E0365 + #[rustfmt::skip] + pub use crate::pub_::RProjOwn; //~ ERROR E0365 + #[rustfmt::skip] + pub use crate::pub_::RProjRef; //~ ERROR E0365 + + // Confirm that the visibility of the original type is not changed. + pub use crate::pub_::{Default, Replace}; +} +pub mod pub_use2 { + // Ok + #[allow(unused_imports)] + pub(crate) use crate::pub_::{DProj, DProjRef, RProj, RProjOwn, RProjRef}; +} + +mod pub_crate { + use pin_project::pin_project; + + #[pin_project(project = DProj, project_ref = DProjRef)] + pub(crate) struct Default(()); + + #[pin_project(project = RProj, project_ref = RProjRef, project_replace = RProjOwn)] + pub(crate) struct Replace(()); +} +pub mod pub_crate_use { + // Ok + #[allow(unused_imports)] + pub(crate) use crate::pub_crate::{DProj, DProjRef, RProj, RProjOwn, RProjRef}; +} + +fn main() {} diff --git a/tests/ui/pin_project/visibility.stderr b/tests/ui/pin_project/visibility.stderr new file mode 100644 index 0000000..4d1b722 --- /dev/null +++ b/tests/ui/pin_project/visibility.stderr @@ -0,0 +1,39 @@ +error[E0365]: `DProj` is only public within the crate, and cannot be re-exported outside + --> tests/ui/pin_project/visibility.rs:15:13 + | +15 | pub use crate::pub_::DProj; //~ ERROR E0365 + | ^^^^^^^^^^^^^^^^^^ re-export of crate public `DProj` + | + = note: consider declaring type or module `DProj` with `pub` + +error[E0365]: `DProjRef` is only public within the crate, and cannot be re-exported outside + --> tests/ui/pin_project/visibility.rs:17:13 + | +17 | pub use crate::pub_::DProjRef; //~ ERROR E0365 + | ^^^^^^^^^^^^^^^^^^^^^ re-export of crate public `DProjRef` + | + = note: consider declaring type or module `DProjRef` with `pub` + +error[E0365]: `RProj` is only public within the crate, and cannot be re-exported outside + --> tests/ui/pin_project/visibility.rs:19:13 + | +19 | pub use crate::pub_::RProj; //~ ERROR E0365 + | ^^^^^^^^^^^^^^^^^^ re-export of crate public `RProj` + | + = note: consider declaring type or module `RProj` with `pub` + +error[E0365]: `RProjOwn` is only public within the crate, and cannot be re-exported outside + --> tests/ui/pin_project/visibility.rs:21:13 + | +21 | pub use crate::pub_::RProjOwn; //~ ERROR E0365 + | ^^^^^^^^^^^^^^^^^^^^^ re-export of crate public `RProjOwn` + | + = note: consider declaring type or module `RProjOwn` with `pub` + +error[E0365]: `RProjRef` is only public within the crate, and cannot be re-exported outside + --> tests/ui/pin_project/visibility.rs:23:13 + | +23 | pub use crate::pub_::RProjRef; //~ ERROR E0365 + | ^^^^^^^^^^^^^^^^^^^^^ re-export of crate public `RProjRef` + | + = note: consider declaring type or module `RProjRef` with `pub` diff --git a/tests/ui/pinned_drop/call-drop-inner.rs b/tests/ui/pinned_drop/call-drop-inner.rs new file mode 100644 index 0000000..9f89942 --- /dev/null +++ b/tests/ui/pinned_drop/call-drop-inner.rs @@ -0,0 +1,17 @@ +use std::pin::Pin; + +use pin_project::{pin_project, pinned_drop}; + +#[pin_project(PinnedDrop)] +struct Struct { + f: bool, +} + +#[pinned_drop] +impl PinnedDrop for Struct { + fn drop(mut self: Pin<&mut Self>) { + __drop_inner(__self); + } +} + +fn main() {} diff --git a/tests/ui/pinned_drop/call-drop-inner.stderr b/tests/ui/pinned_drop/call-drop-inner.stderr new file mode 100644 index 0000000..e3ceebd --- /dev/null +++ b/tests/ui/pinned_drop/call-drop-inner.stderr @@ -0,0 +1,16 @@ +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> tests/ui/pinned_drop/call-drop-inner.rs:13:9 + | +13 | __drop_inner(__self); + | ^^^^^^^^^^^^ ------ argument of type `Pin<&mut Struct>` unexpected + | +note: function defined here + --> tests/ui/pinned_drop/call-drop-inner.rs:10:1 + | +10 | #[pinned_drop] + | ^^^^^^^^^^^^^^ + = note: this error originates in the attribute macro `pinned_drop` (in Nightly builds, run with -Z macro-backtrace for more info) +help: remove the extra argument + | +13 | __drop_inner(); + | ~~~~~~~~~~~~~~ diff --git a/tests/ui/pinned_drop/conditional-drop-impl.rs b/tests/ui/pinned_drop/conditional-drop-impl.rs new file mode 100644 index 0000000..23d756d --- /dev/null +++ b/tests/ui/pinned_drop/conditional-drop-impl.rs @@ -0,0 +1,27 @@ +use std::pin::Pin; + +use pin_project::{pin_project, pinned_drop}; + +// In `Drop` impl, the implementor must specify the same requirement as type definition. + +struct DropImpl { + f: T, +} + +impl Drop for DropImpl { + //~^ ERROR E0367 + fn drop(&mut self) {} +} + +#[pin_project(PinnedDrop)] //~ ERROR E0277 +struct PinnedDropImpl { + #[pin] + f: T, +} + +#[pinned_drop] +impl PinnedDrop for PinnedDropImpl { + fn drop(self: Pin<&mut Self>) {} +} + +fn main() {} diff --git a/tests/ui/pinned_drop/conditional-drop-impl.stderr b/tests/ui/pinned_drop/conditional-drop-impl.stderr new file mode 100644 index 0000000..0587765 --- /dev/null +++ b/tests/ui/pinned_drop/conditional-drop-impl.stderr @@ -0,0 +1,28 @@ +error[E0367]: `Drop` impl requires `T: Unpin` but the struct it is implemented for does not + --> tests/ui/pinned_drop/conditional-drop-impl.rs:11:9 + | +11 | impl Drop for DropImpl { + | ^^^^^ + | +note: the implementor must specify the same requirement + --> tests/ui/pinned_drop/conditional-drop-impl.rs:7:1 + | +7 | struct DropImpl { + | ^^^^^^^^^^^^^^^^^^ + +error[E0277]: `T` cannot be unpinned + --> tests/ui/pinned_drop/conditional-drop-impl.rs:16:15 + | +16 | #[pin_project(PinnedDrop)] //~ ERROR E0277 + | ^^^^^^^^^^ the trait `Unpin` is not implemented for `T` + | + = note: consider using `Box::pin` +note: required because of the requirements on the impl of `PinnedDrop` for `PinnedDropImpl` + --> tests/ui/pinned_drop/conditional-drop-impl.rs:23:16 + | +23 | impl PinnedDrop for PinnedDropImpl { + | ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ +help: consider restricting type parameter `T` + | +17 | struct PinnedDropImpl { + | ++++++++++++++++++++ diff --git a/tests/ui/pinned_drop/forget-pinned-drop-impl.rs b/tests/ui/pinned_drop/forget-pinned-drop-impl.rs new file mode 100644 index 0000000..e31f46f --- /dev/null +++ b/tests/ui/pinned_drop/forget-pinned-drop-impl.rs @@ -0,0 +1,9 @@ +use pin_project::pin_project; + +#[pin_project(PinnedDrop)] //~ ERROR E0277 +struct Struct { + #[pin] + f: u8, +} + +fn main() {} diff --git a/tests/ui/pinned_drop/forget-pinned-drop-impl.stderr b/tests/ui/pinned_drop/forget-pinned-drop-impl.stderr new file mode 100644 index 0000000..ef8a7bf --- /dev/null +++ b/tests/ui/pinned_drop/forget-pinned-drop-impl.stderr @@ -0,0 +1,5 @@ +error[E0277]: the trait bound `Struct: PinnedDrop` is not satisfied + --> tests/ui/pinned_drop/forget-pinned-drop-impl.rs:3:15 + | +3 | #[pin_project(PinnedDrop)] //~ ERROR E0277 + | ^^^^^^^^^^ the trait `PinnedDrop` is not implemented for `Struct` diff --git a/tests/ui/pinned_drop/invalid-self.rs b/tests/ui/pinned_drop/invalid-self.rs new file mode 100644 index 0000000..783167f --- /dev/null +++ b/tests/ui/pinned_drop/invalid-self.rs @@ -0,0 +1,14 @@ +// by-ref binding `ref (mut) self` and sub-patterns `@` are not allowed in receivers (rejected by rustc). + +use std::pin::Pin; + +struct S {} + +impl S { + fn take_ref_self(ref self: Pin<&mut Self>) {} //~ ERROR expected identifier, found keyword `self` + fn take_ref_mut_self(ref mut self: Pin<&mut Self>) {} //~ ERROR expected identifier, found keyword `self` + + fn self_subpat(self @ S {}: Self) {} //~ ERROR expected one of `)`, `,`, or `:`, found `@` +} + +fn main() {} diff --git a/tests/ui/pinned_drop/invalid-self.stderr b/tests/ui/pinned_drop/invalid-self.stderr new file mode 100644 index 0000000..464be5e --- /dev/null +++ b/tests/ui/pinned_drop/invalid-self.stderr @@ -0,0 +1,25 @@ +error: expected identifier, found keyword `self` + --> tests/ui/pinned_drop/invalid-self.rs:8:26 + | +8 | fn take_ref_self(ref self: Pin<&mut Self>) {} //~ ERROR expected identifier, found keyword `self` + | ^^^^ expected identifier, found keyword + +error: expected identifier, found keyword `self` + --> tests/ui/pinned_drop/invalid-self.rs:9:34 + | +9 | fn take_ref_mut_self(ref mut self: Pin<&mut Self>) {} //~ ERROR expected identifier, found keyword `self` + | ^^^^ expected identifier, found keyword + +error: expected parameter name, found `@` + --> tests/ui/pinned_drop/invalid-self.rs:11:25 + | +11 | fn self_subpat(self @ S {}: Self) {} //~ ERROR expected one of `)`, `,`, or `:`, found `@` + | ^ expected parameter name + +error: expected one of `)`, `,`, or `:`, found `@` + --> tests/ui/pinned_drop/invalid-self.rs:11:25 + | +11 | fn self_subpat(self @ S {}: Self) {} //~ ERROR expected one of `)`, `,`, or `:`, found `@` + | -^ expected one of `)`, `,`, or `:` + | | + | help: missing `,` diff --git a/tests/ui/pinned_drop/invalid.rs b/tests/ui/pinned_drop/invalid.rs new file mode 100644 index 0000000..fdadf8a --- /dev/null +++ b/tests/ui/pinned_drop/invalid.rs @@ -0,0 +1,231 @@ +mod argument { + use std::pin::Pin; + + use pin_project::{pin_project, pinned_drop}; + + #[pin_project(PinnedDrop)] + struct UnexpectedArg1(()); + + #[pinned_drop(foo)] //~ ERROR unexpected token + impl PinnedDrop for UnexpectedArg1 { + fn drop(self: Pin<&mut Self>) {} + } + + #[pin_project(PinnedDrop)] + struct UnexpectedArg2(()); + + #[pinned_drop()] // Ok + impl PinnedDrop for UnexpectedArg2 { + fn drop(self: Pin<&mut Self>) {} + } +} + +mod attribute { + use pin_project::{pin_project, pinned_drop}; + + #[pin_project(PinnedDrop)] + struct Duplicate(()); + + #[pinned_drop] + #[pinned_drop] //~ ERROR duplicate #[pinned_drop] attribute + impl PinnedDrop for Duplicate { + fn drop(self: Pin<&mut Self>) {} + } +} + +mod item { + use pin_project::{pin_project, pinned_drop}; + + #[pin_project(PinnedDrop)] + struct TraitImpl(()); + + #[pinned_drop] + impl Drop for TraitImpl {} //~ ERROR may only be used on implementation for the `PinnedDrop` trait + + #[pin_project(PinnedDrop)] + struct InherentImpl(()); + + #[pinned_drop] + impl InherentImpl {} //~ ERROR may only be used on implementation for the `PinnedDrop` trait + + #[pinned_drop] + fn func(_: Pin<&mut ()>) {} //~ ERROR expected `impl` +} + +mod unsafety { + use pin_project::{pin_project, pinned_drop}; + + #[pin_project(PinnedDrop)] + struct Impl(()); + + #[pinned_drop] + unsafe impl PinnedDrop for Impl { + //~^ ERROR implementing the trait `PinnedDrop` is not unsafe + fn drop(self: Pin<&mut Self>) {} + } + + #[pin_project(PinnedDrop)] + struct Method(()); + + #[pinned_drop] + impl PinnedDrop for Method { + unsafe fn drop(self: Pin<&mut Self>) {} //~ ERROR implementing the method `drop` is not unsafe + } +} + +mod assoc_item { + use pin_project::{pin_project, pinned_drop}; + + #[pin_project(PinnedDrop)] + struct Empty(()); + + #[pinned_drop] + impl PinnedDrop for Empty {} //~ ERROR not all trait items implemented, missing: `drop` + + #[pin_project(PinnedDrop)] + struct Const1(()); + + #[pinned_drop] + impl PinnedDrop for Const1 { + const A: u8 = 0; //~ ERROR const `A` is not a member of trait `PinnedDrop` + fn drop(self: Pin<&mut Self>) {} + } + + #[pin_project(PinnedDrop)] + struct Const2(()); + + #[pinned_drop] + impl PinnedDrop for Const2 { + fn drop(self: Pin<&mut Self>) {} + const A: u8 = 0; //~ ERROR const `A` is not a member of trait `PinnedDrop` + } + + #[pin_project(PinnedDrop)] + struct Type1(()); + + #[pinned_drop] + impl PinnedDrop for Type1 { + type A = u8; //~ ERROR type `A` is not a member of trait `PinnedDrop` + fn drop(self: Pin<&mut Self>) {} + } + + #[pin_project(PinnedDrop)] + struct Type2(()); + + #[pinned_drop] + impl PinnedDrop for Type2 { + fn drop(self: Pin<&mut Self>) {} + type A = u8; //~ ERROR type `A` is not a member of trait `PinnedDrop` + } + + #[pin_project(PinnedDrop)] + struct Duplicate(()); + + #[pinned_drop] + impl PinnedDrop for Duplicate { + fn drop(self: Pin<&mut Self>) {} + fn drop(self: Pin<&mut Self>) {} //~ ERROR duplicate definitions with name `drop` + } +} + +mod method { + use std::pin::Pin; + + use pin_project::{pin_project, pinned_drop}; + + #[pin_project(PinnedDrop)] + struct RetUnit(()); + + #[pinned_drop] + impl PinnedDrop for RetUnit { + fn drop(self: Pin<&mut Self>) -> () {} // Ok + } + + #[pin_project(PinnedDrop)] + struct RetTy(()); + + #[pinned_drop] + impl PinnedDrop for RetTy { + fn drop(self: Pin<&mut Self>) -> Self {} //~ ERROR method `drop` must return the unit type + } + + #[pin_project(PinnedDrop)] + struct NoArg(()); + + #[pinned_drop] + impl PinnedDrop for NoArg { + fn drop() {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>` + } + + #[pin_project(PinnedDrop)] + struct MultiArg(()); + + #[pinned_drop] + impl PinnedDrop for MultiArg { + fn drop(self: Pin<&mut Self>, _: ()) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>` + } + + #[pin_project(PinnedDrop)] + struct InvalidArg1(()); + + #[pinned_drop] + impl PinnedDrop for InvalidArg1 { + fn drop(&mut self) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>` + } + + #[pin_project(PinnedDrop)] + struct InvalidArg2(()); + + #[pinned_drop] + impl PinnedDrop for InvalidArg2 { + fn drop(_: Pin<&mut Self>) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>` + } + + #[pin_project(PinnedDrop)] + struct InvalidArg3(()); + + #[pinned_drop] + impl PinnedDrop for InvalidArg3 { + fn drop(self: Pin<&Self>) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>` + } + + #[pin_project(PinnedDrop)] + struct InvalidArg4(()); + + #[pinned_drop] + impl PinnedDrop for InvalidArg4 { + fn drop(self: Pin<&mut ()>) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>` + } + + #[pin_project(PinnedDrop)] + struct InvalidName(()); + + #[pinned_drop] + impl PinnedDrop for InvalidName { + fn pinned_drop(self: Pin<&mut Self>) {} //~ ERROR method `pinned_drop` is not a member of trait `PinnedDrop + } +} + +mod self_ty { + use pin_project::pinned_drop; + + #[pinned_drop] + impl PinnedDrop for () { + //~^ ERROR implementing the trait `PinnedDrop` on this type is unsupported + fn drop(self: Pin<&mut Self>) {} + } + + #[pinned_drop] + impl PinnedDrop for &mut A { + //~^ ERROR implementing the trait `PinnedDrop` on this type is unsupported + fn drop(self: Pin<&mut Self>) {} + } + + #[pinned_drop] + impl PinnedDrop for [A] { + //~^ ERROR implementing the trait `PinnedDrop` on this type is unsupported + fn drop(self: Pin<&mut Self>) {} + } +} + +fn main() {} diff --git a/tests/ui/pinned_drop/invalid.stderr b/tests/ui/pinned_drop/invalid.stderr new file mode 100644 index 0000000..d509964 --- /dev/null +++ b/tests/ui/pinned_drop/invalid.stderr @@ -0,0 +1,143 @@ +error: unexpected token: `foo` + --> tests/ui/pinned_drop/invalid.rs:9:19 + | +9 | #[pinned_drop(foo)] //~ ERROR unexpected token + | ^^^ + +error: duplicate #[pinned_drop] attribute + --> tests/ui/pinned_drop/invalid.rs:30:5 + | +30 | #[pinned_drop] //~ ERROR duplicate #[pinned_drop] attribute + | ^^^^^^^^^^^^^^ + +error: #[pinned_drop] may only be used on implementation for the `PinnedDrop` trait + --> tests/ui/pinned_drop/invalid.rs:43:10 + | +43 | impl Drop for TraitImpl {} //~ ERROR may only be used on implementation for the `PinnedDrop` trait + | ^^^^ + +error: #[pinned_drop] may only be used on implementation for the `PinnedDrop` trait + --> tests/ui/pinned_drop/invalid.rs:49:10 + | +49 | impl InherentImpl {} //~ ERROR may only be used on implementation for the `PinnedDrop` trait + | ^^^^^^^^^^^^ + +error: expected `impl` + --> tests/ui/pinned_drop/invalid.rs:52:5 + | +52 | fn func(_: Pin<&mut ()>) {} //~ ERROR expected `impl` + | ^^ + +error: implementing the trait `PinnedDrop` is not unsafe + --> tests/ui/pinned_drop/invalid.rs:62:5 + | +62 | unsafe impl PinnedDrop for Impl { + | ^^^^^^ + +error: implementing the method `drop` is not unsafe + --> tests/ui/pinned_drop/invalid.rs:72:9 + | +72 | unsafe fn drop(self: Pin<&mut Self>) {} //~ ERROR implementing the method `drop` is not unsafe + | ^^^^^^ + +error: not all trait items implemented, missing: `drop` + --> tests/ui/pinned_drop/invalid.rs:83:5 + | +83 | impl PinnedDrop for Empty {} //~ ERROR not all trait items implemented, missing: `drop` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: const `A` is not a member of trait `PinnedDrop` + --> tests/ui/pinned_drop/invalid.rs:90:9 + | +90 | const A: u8 = 0; //~ ERROR const `A` is not a member of trait `PinnedDrop` + | ^^^^^^^^^^^^^^^^ + +error: const `A` is not a member of trait `PinnedDrop` + --> tests/ui/pinned_drop/invalid.rs:100:9 + | +100 | const A: u8 = 0; //~ ERROR const `A` is not a member of trait `PinnedDrop` + | ^^^^^^^^^^^^^^^^ + +error: type `A` is not a member of trait `PinnedDrop` + --> tests/ui/pinned_drop/invalid.rs:108:9 + | +108 | type A = u8; //~ ERROR type `A` is not a member of trait `PinnedDrop` + | ^^^^^^^^^^^^ + +error: type `A` is not a member of trait `PinnedDrop` + --> tests/ui/pinned_drop/invalid.rs:118:9 + | +118 | type A = u8; //~ ERROR type `A` is not a member of trait `PinnedDrop` + | ^^^^^^^^^^^^ + +error: duplicate definitions with name `drop` + --> tests/ui/pinned_drop/invalid.rs:127:9 + | +127 | fn drop(self: Pin<&mut Self>) {} //~ ERROR duplicate definitions with name `drop` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: method `drop` must return the unit type + --> tests/ui/pinned_drop/invalid.rs:149:42 + | +149 | fn drop(self: Pin<&mut Self>) -> Self {} //~ ERROR method `drop` must return the unit type + | ^^^^ + +error: method `drop` must take an argument `self: Pin<&mut Self>` + --> tests/ui/pinned_drop/invalid.rs:157:16 + | +157 | fn drop() {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>` + | ^^ + +error: method `drop` must take an argument `self: Pin<&mut Self>` + --> tests/ui/pinned_drop/invalid.rs:165:17 + | +165 | fn drop(self: Pin<&mut Self>, _: ()) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: method `drop` must take an argument `self: Pin<&mut Self>` + --> tests/ui/pinned_drop/invalid.rs:173:17 + | +173 | fn drop(&mut self) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>` + | ^^^^^^^^^ + +error: method `drop` must take an argument `self: Pin<&mut Self>` + --> tests/ui/pinned_drop/invalid.rs:181:17 + | +181 | fn drop(_: Pin<&mut Self>) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>` + | ^^^^^^^^^^^^^^^^^ + +error: method `drop` must take an argument `self: Pin<&mut Self>` + --> tests/ui/pinned_drop/invalid.rs:189:17 + | +189 | fn drop(self: Pin<&Self>) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>` + | ^^^^^^^^^^^^^^^^ + +error: method `drop` must take an argument `self: Pin<&mut Self>` + --> tests/ui/pinned_drop/invalid.rs:197:17 + | +197 | fn drop(self: Pin<&mut ()>) {} //~ ERROR method `drop` must take an argument `self: Pin<&mut Self>` + | ^^^^^^^^^^^^^^^^^^ + +error: method `pinned_drop` is not a member of trait `PinnedDrop + --> tests/ui/pinned_drop/invalid.rs:205:12 + | +205 | fn pinned_drop(self: Pin<&mut Self>) {} //~ ERROR method `pinned_drop` is not a member of trait `PinnedDrop + | ^^^^^^^^^^^ + +error: implementing the trait `PinnedDrop` on this type is unsupported + --> tests/ui/pinned_drop/invalid.rs:213:25 + | +213 | impl PinnedDrop for () { + | ^^ + +error: implementing the trait `PinnedDrop` on this type is unsupported + --> tests/ui/pinned_drop/invalid.rs:219:25 + | +219 | impl PinnedDrop for &mut A { + | ^^^^^^ + +error: implementing the trait `PinnedDrop` on this type is unsupported + --> tests/ui/pinned_drop/invalid.rs:225:25 + | +225 | impl PinnedDrop for [A] { + | ^^^ diff --git a/tests/ui/pinned_drop/pinned-drop-no-attr-arg.rs b/tests/ui/pinned_drop/pinned-drop-no-attr-arg.rs new file mode 100644 index 0000000..391f290 --- /dev/null +++ b/tests/ui/pinned_drop/pinned-drop-no-attr-arg.rs @@ -0,0 +1,17 @@ +use std::pin::Pin; + +use pin_project::{pin_project, pinned_drop}; + +#[pin_project] +struct S { + #[pin] + f: u8, +} + +#[pinned_drop] +impl PinnedDrop for S { + //~^ ERROR E0119 + fn drop(self: Pin<&mut Self>) {} +} + +fn main() {} diff --git a/tests/ui/pinned_drop/pinned-drop-no-attr-arg.stderr b/tests/ui/pinned_drop/pinned-drop-no-attr-arg.stderr new file mode 100644 index 0000000..2542254 --- /dev/null +++ b/tests/ui/pinned_drop/pinned-drop-no-attr-arg.stderr @@ -0,0 +1,8 @@ +error[E0119]: conflicting implementations of trait `_::_pin_project::__private::PinnedDrop` for type `S` + --> tests/ui/pinned_drop/pinned-drop-no-attr-arg.rs:12:1 + | +5 | #[pin_project] + | -------------- first implementation here +... +12 | impl PinnedDrop for S { + | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S` diff --git a/tests/ui/pinned_drop/self.rs b/tests/ui/pinned_drop/self.rs new file mode 100644 index 0000000..ff63402 --- /dev/null +++ b/tests/ui/pinned_drop/self.rs @@ -0,0 +1,58 @@ +pub mod self_in_macro_def { + use std::pin::Pin; + + use pin_project::{pin_project, pinned_drop}; + + #[pin_project(PinnedDrop)] + pub struct S { + f: (), + } + + #[pinned_drop] + impl PinnedDrop for S { + fn drop(self: Pin<&mut Self>) { + macro_rules! t { + () => {{ + let _ = self; //~ ERROR E0434 + + fn f(self: ()) {} //~ ERROR `self` parameter is only allowed in associated functions + }}; + } + t!(); + } + } +} + +pub mod self_span { + use std::pin::Pin; + + use pin_project::{pin_project, pinned_drop}; + + #[pin_project(PinnedDrop)] + pub struct S { + f: (), + } + + #[pinned_drop] + impl PinnedDrop for S { + fn drop(self: Pin<&mut Self>) { + let _: () = self; //~ ERROR E0308 + let _: Self = Self; //~ ERROR E0423 + } + } + + #[pin_project(PinnedDrop)] + pub enum E { + V { f: () }, + } + + #[pinned_drop] + impl PinnedDrop for E { + fn drop(self: Pin<&mut Self>) { + let _: () = self; //~ ERROR E0308 + let _: Self = Self::V; //~ ERROR E0533 + } + } +} + +fn main() {} diff --git a/tests/ui/pinned_drop/self.stderr b/tests/ui/pinned_drop/self.stderr new file mode 100644 index 0000000..a19d5a0 --- /dev/null +++ b/tests/ui/pinned_drop/self.stderr @@ -0,0 +1,62 @@ +error: `self` parameter is only allowed in associated functions + --> tests/ui/pinned_drop/self.rs:18:26 + | +18 | fn f(self: ()) {} //~ ERROR `self` parameter is only allowed in associated functions + | ^^^^ not semantically valid as function parameter +... +21 | t!(); + | ---- in this macro invocation + | + = note: associated functions are those in `impl` or `trait` definitions + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0434]: can't capture dynamic environment in a fn item + --> tests/ui/pinned_drop/self.rs:16:29 + | +16 | let _ = self; //~ ERROR E0434 + | ^^^^ +... +21 | t!(); + | ---- in this macro invocation + | + = help: use the `|| { ... }` closure form instead + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0423]: expected value, found struct `S` + --> tests/ui/pinned_drop/self.rs:40:27 + | +32 | / pub struct S { +33 | | f: (), +34 | | } + | |_____- `S` defined here +... +40 | let _: Self = Self; //~ ERROR E0423 + | ^^^^ help: use struct literal syntax instead: `S { f: val }` + +error[E0308]: mismatched types + --> tests/ui/pinned_drop/self.rs:39:25 + | +39 | let _: () = self; //~ ERROR E0308 + | -- ^^^^ expected `()`, found struct `Pin` + | | + | expected due to this + | + = note: expected unit type `()` + found struct `Pin<&mut self_span::S>` + +error[E0308]: mismatched types + --> tests/ui/pinned_drop/self.rs:52:25 + | +52 | let _: () = self; //~ ERROR E0308 + | -- ^^^^ expected `()`, found struct `Pin` + | | + | expected due to this + | + = note: expected unit type `()` + found struct `Pin<&mut E>` + +error[E0533]: expected unit struct, unit variant or constant, found struct variant `E::V` + --> tests/ui/pinned_drop/self.rs:53:27 + | +53 | let _: Self = Self::V; //~ ERROR E0533 + | ^^^^^^^ diff --git a/tests/ui/pinned_drop/unsafe-call.rs b/tests/ui/pinned_drop/unsafe-call.rs new file mode 100644 index 0000000..3ee2b56 --- /dev/null +++ b/tests/ui/pinned_drop/unsafe-call.rs @@ -0,0 +1,18 @@ +use std::pin::Pin; + +use pin_project::{pin_project, pinned_drop}; + +#[pin_project(PinnedDrop)] +struct S { + #[pin] + f: u8, +} + +#[pinned_drop] +impl PinnedDrop for S { + fn drop(self: Pin<&mut Self>) { + self.project().f.get_unchecked_mut(); //~ ERROR call to unsafe function is unsafe and requires unsafe function or block [E0133] + } +} + +fn main() {} diff --git a/tests/ui/pinned_drop/unsafe-call.stderr b/tests/ui/pinned_drop/unsafe-call.stderr new file mode 100644 index 0000000..9f7dd44 --- /dev/null +++ b/tests/ui/pinned_drop/unsafe-call.stderr @@ -0,0 +1,7 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> tests/ui/pinned_drop/unsafe-call.rs:14:9 + | +14 | self.project().f.get_unchecked_mut(); //~ ERROR call to unsafe function is unsafe and requires unsafe function or block [E0133] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior diff --git a/tests/ui/unsafe_unpin/conflict-unpin.rs b/tests/ui/unsafe_unpin/conflict-unpin.rs new file mode 100644 index 0000000..ac9d1f8 --- /dev/null +++ b/tests/ui/unsafe_unpin/conflict-unpin.rs @@ -0,0 +1,30 @@ +use pin_project::pin_project; + +#[pin_project(UnsafeUnpin)] //~ ERROR E0119 +struct Foo { + #[pin] + f1: T, + f2: U, +} + +impl Unpin for Foo where T: Unpin {} + +#[pin_project(UnsafeUnpin)] //~ ERROR E0119 +struct Bar { + #[pin] + f1: T, + f2: U, +} + +impl Unpin for Bar {} + +#[pin_project(UnsafeUnpin)] //~ ERROR E0119 +struct Baz { + #[pin] + f1: T, + f2: U, +} + +impl Unpin for Baz {} + +fn main() {} diff --git a/tests/ui/unsafe_unpin/conflict-unpin.stderr b/tests/ui/unsafe_unpin/conflict-unpin.stderr new file mode 100644 index 0000000..0e89b03 --- /dev/null +++ b/tests/ui/unsafe_unpin/conflict-unpin.stderr @@ -0,0 +1,32 @@ +error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Foo<_, _>` + --> tests/ui/unsafe_unpin/conflict-unpin.rs:3:15 + | +3 | #[pin_project(UnsafeUnpin)] //~ ERROR E0119 + | ^^^^^^^^^^^ conflicting implementation for `Foo<_, _>` +... +10 | impl Unpin for Foo where T: Unpin {} + | ------------------------------ first implementation here + | + = note: upstream crates may add a new impl of trait `_::_pin_project::UnsafeUnpin` for type `_::_pin_project::__private::Wrapper<'_, Foo<_, _>>` in future versions + +error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Bar<_, _>` + --> tests/ui/unsafe_unpin/conflict-unpin.rs:12:15 + | +12 | #[pin_project(UnsafeUnpin)] //~ ERROR E0119 + | ^^^^^^^^^^^ conflicting implementation for `Bar<_, _>` +... +19 | impl Unpin for Bar {} + | ------------------------------ first implementation here + | + = note: upstream crates may add a new impl of trait `_::_pin_project::UnsafeUnpin` for type `_::_pin_project::__private::Wrapper<'_, Bar<_, _>>` in future versions + +error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Baz<_, _>` + --> tests/ui/unsafe_unpin/conflict-unpin.rs:21:15 + | +21 | #[pin_project(UnsafeUnpin)] //~ ERROR E0119 + | ^^^^^^^^^^^ conflicting implementation for `Baz<_, _>` +... +28 | impl Unpin for Baz {} + | -------------------------------------------- first implementation here + | + = note: upstream crates may add a new impl of trait `_::_pin_project::UnsafeUnpin` for type `_::_pin_project::__private::Wrapper<'_, Baz<_, _>>` in future versions diff --git a/tests/ui/unstable-features/README.md b/tests/ui/unstable-features/README.md new file mode 100644 index 0000000..96f370c --- /dev/null +++ b/tests/ui/unstable-features/README.md @@ -0,0 +1,7 @@ +# UI tests for unstable features + +These tests check how the guarantees and features provided by pin-project +interact with unstable language features. + +The names of the files contained in this directory need to begin with the name +of the feature. diff --git a/tests/ui/unstable-features/marker_trait_attr-feature-gate.rs b/tests/ui/unstable-features/marker_trait_attr-feature-gate.rs new file mode 100644 index 0000000..542250b --- /dev/null +++ b/tests/ui/unstable-features/marker_trait_attr-feature-gate.rs @@ -0,0 +1,20 @@ +// Note: If you change this test, change 'marker_trait_attr.rs' at the same time. + +use std::marker::PhantomPinned; + +use pin_project::pin_project; + +#[pin_project] //~ ERROR E0119 +struct Struct { + #[pin] + f: T, +} + +// unsound Unpin impl +impl Unpin for Struct {} + +fn is_unpin() {} + +fn main() { + is_unpin::>() +} diff --git a/tests/ui/unstable-features/marker_trait_attr-feature-gate.stderr b/tests/ui/unstable-features/marker_trait_attr-feature-gate.stderr new file mode 100644 index 0000000..3412f2e --- /dev/null +++ b/tests/ui/unstable-features/marker_trait_attr-feature-gate.stderr @@ -0,0 +1,10 @@ +error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Struct<_>` + --> tests/ui/unstable-features/marker_trait_attr-feature-gate.rs:7:1 + | +7 | #[pin_project] //~ ERROR E0119 + | ^^^^^^^^^^^^^^ conflicting implementation for `Struct<_>` +... +14 | impl Unpin for Struct {} + | --------------------------- first implementation here + | + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/unstable-features/marker_trait_attr.rs b/tests/ui/unstable-features/marker_trait_attr.rs new file mode 100644 index 0000000..9c8e664 --- /dev/null +++ b/tests/ui/unstable-features/marker_trait_attr.rs @@ -0,0 +1,26 @@ +// Note: If you change this test, change 'marker_trait_attr-feature-gate.rs' at the same time. + +// marker_trait_attr +// Tracking issue: https://github.com/rust-lang/rust/issues/29864 +#![feature(marker_trait_attr)] + +// See https://github.com/taiki-e/pin-project/issues/105#issuecomment-535355974 + +use std::marker::PhantomPinned; + +use pin_project::pin_project; + +#[pin_project] //~ ERROR E0119 +struct Struct { + #[pin] + f: T, +} + +// unsound Unpin impl +impl Unpin for Struct {} + +fn is_unpin() {} + +fn main() { + is_unpin::>() +} diff --git a/tests/ui/unstable-features/marker_trait_attr.stderr b/tests/ui/unstable-features/marker_trait_attr.stderr new file mode 100644 index 0000000..2b68c80 --- /dev/null +++ b/tests/ui/unstable-features/marker_trait_attr.stderr @@ -0,0 +1,10 @@ +error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Struct<_>` + --> tests/ui/unstable-features/marker_trait_attr.rs:13:1 + | +13 | #[pin_project] //~ ERROR E0119 + | ^^^^^^^^^^^^^^ conflicting implementation for `Struct<_>` +... +20 | impl Unpin for Struct {} + | --------------------------- first implementation here + | + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/unstable-features/negative_impls.rs b/tests/ui/unstable-features/negative_impls.rs new file mode 100644 index 0000000..9605642 --- /dev/null +++ b/tests/ui/unstable-features/negative_impls.rs @@ -0,0 +1,23 @@ +#![feature(negative_impls)] +#![deny(suspicious_auto_trait_impls)] + +// https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/design.20meeting.3A.20backlog.20bonanza/near/269471299 +// https://github.com/taiki-e/pin-project/issues/340 + +#[pin_project::pin_project] +struct Foo { + #[pin] + pinned: Pinned, + + unpinned: Unpinned, +} + +struct MyPhantomPinned {} +impl !Unpin for MyPhantomPinned {} +impl Unpin for Foo {} + +fn is_unpin() {} + +fn main() { + is_unpin::>() +} diff --git a/tests/ui/unstable-features/negative_impls.stderr b/tests/ui/unstable-features/negative_impls.stderr new file mode 100644 index 0000000..0d99e2b --- /dev/null +++ b/tests/ui/unstable-features/negative_impls.stderr @@ -0,0 +1,19 @@ +error: cross-crate traits with a default impl, like `Unpin`, should not be specialized + --> tests/ui/unstable-features/negative_impls.rs:17:1 + | +17 | impl Unpin for Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui/unstable-features/negative_impls.rs:2:9 + | +2 | #![deny(suspicious_auto_trait_impls)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this will change its meaning in a future release! + = note: for more information, see issue #93367 + = note: `MyPhantomPinned` is not a generic parameter +note: try using the same sequence of generic parameters as the struct definition + --> tests/ui/unstable-features/negative_impls.rs:8:1 + | +8 | struct Foo { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unstable-features/overlapping_marker_traits-feature-gate.rs b/tests/ui/unstable-features/overlapping_marker_traits-feature-gate.rs new file mode 100644 index 0000000..012c870 --- /dev/null +++ b/tests/ui/unstable-features/overlapping_marker_traits-feature-gate.rs @@ -0,0 +1,20 @@ +// Note: If you change this test, change 'overlapping_marker_traits.rs' at the same time. + +use std::marker::PhantomPinned; + +use pin_project::pin_project; + +#[pin_project] //~ ERROR E0119 +struct Struct { + #[pin] + f: T, +} + +// unsound Unpin impl +impl Unpin for Struct {} + +fn is_unpin() {} + +fn main() { + is_unpin::>() +} diff --git a/tests/ui/unstable-features/overlapping_marker_traits-feature-gate.stderr b/tests/ui/unstable-features/overlapping_marker_traits-feature-gate.stderr new file mode 100644 index 0000000..918d804 --- /dev/null +++ b/tests/ui/unstable-features/overlapping_marker_traits-feature-gate.stderr @@ -0,0 +1,10 @@ +error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Struct<_>` + --> tests/ui/unstable-features/overlapping_marker_traits-feature-gate.rs:7:1 + | +7 | #[pin_project] //~ ERROR E0119 + | ^^^^^^^^^^^^^^ conflicting implementation for `Struct<_>` +... +14 | impl Unpin for Struct {} + | --------------------------- first implementation here + | + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/unstable-features/overlapping_marker_traits.rs b/tests/ui/unstable-features/overlapping_marker_traits.rs new file mode 100644 index 0000000..8dc27c1 --- /dev/null +++ b/tests/ui/unstable-features/overlapping_marker_traits.rs @@ -0,0 +1,30 @@ +// Note: If you change this test, change 'overlapping_marker_traits-feature-gate.rs' at the same time. + +// This feature could break the guarantee for Unpin provided by pin-project, +// but was removed in https://github.com/rust-lang/rust/pull/68544 (nightly-2020-02-06). +// Refs: +// - https://github.com/rust-lang/rust/issues/29864#issuecomment-515780867 +// - https://github.com/taiki-e/pin-project/issues/105 + +// overlapping_marker_traits +// Tracking issue: https://github.com/rust-lang/rust/issues/29864 +#![feature(overlapping_marker_traits)] + +use std::marker::PhantomPinned; + +use pin_project::pin_project; + +#[pin_project] +struct Struct { + #[pin] + f: T, +} + +// unsound Unpin impl +impl Unpin for Struct {} + +fn is_unpin() {} + +fn main() { + is_unpin::>() +} diff --git a/tests/ui/unstable-features/overlapping_marker_traits.stderr b/tests/ui/unstable-features/overlapping_marker_traits.stderr new file mode 100644 index 0000000..3e8411d --- /dev/null +++ b/tests/ui/unstable-features/overlapping_marker_traits.stderr @@ -0,0 +1,18 @@ +error[E0557]: feature has been removed + --> tests/ui/unstable-features/overlapping_marker_traits.rs:11:12 + | +11 | #![feature(overlapping_marker_traits)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ feature has been removed + | + = note: removed in favor of `#![feature(marker_trait_attr)]` + +error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Struct<_>` + --> tests/ui/unstable-features/overlapping_marker_traits.rs:17:1 + | +17 | #[pin_project] + | ^^^^^^^^^^^^^^ conflicting implementation for `Struct<_>` +... +24 | impl Unpin for Struct {} + | --------------------------- first implementation here + | + = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/unstable-features/trivial_bounds-feature-gate.rs b/tests/ui/unstable-features/trivial_bounds-feature-gate.rs new file mode 100644 index 0000000..f8467b0 --- /dev/null +++ b/tests/ui/unstable-features/trivial_bounds-feature-gate.rs @@ -0,0 +1,53 @@ +// Note: If you change this test, change 'trivial_bounds.rs' at the same time. + +mod phantom_pinned { + use std::marker::{PhantomData, PhantomPinned}; + + struct A(PhantomPinned); + + impl Unpin for A where PhantomPinned: Unpin {} //~ ERROR E0277 + + struct Wrapper(T); + + impl Unpin for Wrapper where T: Unpin {} + + struct B(PhantomPinned); + + impl Unpin for B where Wrapper: Unpin {} //~ ERROR E0277 + + struct WrapperWithLifetime<'a, T>(PhantomData<&'a ()>, T); + + impl Unpin for WrapperWithLifetime<'_, T> where T: Unpin {} + + struct C(PhantomPinned); + + impl<'a> Unpin for C where WrapperWithLifetime<'a, PhantomPinned>: Unpin {} // Ok +} + +mod inner { + use std::marker::{PhantomData, PhantomPinned}; + + struct Inner(PhantomPinned); + + struct A(Inner); + + impl Unpin for A where Inner: Unpin {} //~ ERROR E0277 + + struct Wrapper(T); + + impl Unpin for Wrapper where T: Unpin {} + + struct B(Inner); + + impl Unpin for B where Wrapper: Unpin {} //~ ERROR E0277 + + struct WrapperWithLifetime<'a, T>(PhantomData<&'a ()>, T); + + impl Unpin for WrapperWithLifetime<'_, T> where T: Unpin {} + + struct C(Inner); + + impl<'a> Unpin for C where WrapperWithLifetime<'a, Inner>: Unpin {} // Ok +} + +fn main() {} diff --git a/tests/ui/unstable-features/trivial_bounds-feature-gate.stderr b/tests/ui/unstable-features/trivial_bounds-feature-gate.stderr new file mode 100644 index 0000000..2e31658 --- /dev/null +++ b/tests/ui/unstable-features/trivial_bounds-feature-gate.stderr @@ -0,0 +1,59 @@ +error[E0277]: `PhantomPinned` cannot be unpinned + --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:8:28 + | +8 | impl Unpin for A where PhantomPinned: Unpin {} //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `PhantomPinned` + | + = note: consider using `Box::pin` + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: `PhantomPinned` cannot be unpinned + --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:16:28 + | +16 | impl Unpin for B where Wrapper: Unpin {} //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `PhantomPinned` + | + = note: consider using `Box::pin` +note: required because of the requirements on the impl of `Unpin` for `phantom_pinned::Wrapper` + --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:12:13 + | +12 | impl Unpin for Wrapper where T: Unpin {} + | ^^^^^ ^^^^^^^^^^ + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: `PhantomPinned` cannot be unpinned + --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:34:28 + | +34 | impl Unpin for A where Inner: Unpin {} //~ ERROR E0277 + | ^^^^^^^^^^^^ within `Inner`, the trait `Unpin` is not implemented for `PhantomPinned` + | + = note: consider using `Box::pin` +note: required because it appears within the type `Inner` + --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:30:12 + | +30 | struct Inner(PhantomPinned); + | ^^^^^ + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: `PhantomPinned` cannot be unpinned + --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:42:28 + | +42 | impl Unpin for B where Wrapper: Unpin {} //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^^ within `Inner`, the trait `Unpin` is not implemented for `PhantomPinned` + | + = note: consider using `Box::pin` +note: required because it appears within the type `Inner` + --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:30:12 + | +30 | struct Inner(PhantomPinned); + | ^^^^^ +note: required because of the requirements on the impl of `Unpin` for `inner::Wrapper` + --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:38:13 + | +38 | impl Unpin for Wrapper where T: Unpin {} + | ^^^^^ ^^^^^^^^^^ + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable diff --git a/tests/ui/unstable-features/trivial_bounds.rs b/tests/ui/unstable-features/trivial_bounds.rs new file mode 100644 index 0000000..41f885d --- /dev/null +++ b/tests/ui/unstable-features/trivial_bounds.rs @@ -0,0 +1,38 @@ +// Note: If you change this test, change 'trivial_bounds-feature-gate.rs' at the same time. + +// trivial_bounds +// Tracking issue: https://github.com/rust-lang/rust/issues/48214 +#![feature(trivial_bounds)] +#![deny(trivial_bounds)] + +use std::marker::{PhantomData, PhantomPinned}; + +fn inner() { + struct Inner(PhantomPinned); + + struct A(PhantomPinned); + + impl Unpin for A where PhantomPinned: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters + + struct B(Inner); + + impl Unpin for B where Inner: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters + + struct Wrapper(T); + + impl Unpin for Wrapper where T: Unpin {} + + struct C(Inner); + + impl Unpin for C where Wrapper: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters + + struct WrapperWithLifetime<'a, T>(PhantomData<&'a ()>, T); + + impl Unpin for WrapperWithLifetime<'_, T> where T: Unpin {} + + struct D(Inner); + + impl<'a> Unpin for D where WrapperWithLifetime<'a, Inner>: Unpin {} // Ok +} + +fn main() {} diff --git a/tests/ui/unstable-features/trivial_bounds.stderr b/tests/ui/unstable-features/trivial_bounds.stderr new file mode 100644 index 0000000..23f45c7 --- /dev/null +++ b/tests/ui/unstable-features/trivial_bounds.stderr @@ -0,0 +1,23 @@ +error: trait bound PhantomPinned: Unpin does not depend on any type or lifetime parameters + --> tests/ui/unstable-features/trivial_bounds.rs:15:43 + | +15 | impl Unpin for A where PhantomPinned: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters + | ^^^^^ + | +note: the lint level is defined here + --> tests/ui/unstable-features/trivial_bounds.rs:6:9 + | +6 | #![deny(trivial_bounds)] + | ^^^^^^^^^^^^^^ + +error: trait bound Inner: Unpin does not depend on any type or lifetime parameters + --> tests/ui/unstable-features/trivial_bounds.rs:19:35 + | +19 | impl Unpin for B where Inner: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters + | ^^^^^ + +error: trait bound Wrapper: Unpin does not depend on any type or lifetime parameters + --> tests/ui/unstable-features/trivial_bounds.rs:27:44 + | +27 | impl Unpin for C where Wrapper: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters + | ^^^^^ diff --git a/tests/unsafe_unpin.rs b/tests/unsafe_unpin.rs new file mode 100644 index 0000000..8b6411c --- /dev/null +++ b/tests/unsafe_unpin.rs @@ -0,0 +1,50 @@ +#![warn(rust_2018_idioms, single_use_lifetimes)] +#![allow(dead_code)] + +#[macro_use] +mod auxiliary; + +use std::marker::PhantomPinned; + +use pin_project::{pin_project, UnsafeUnpin}; + +#[pin_project(UnsafeUnpin)] +pub struct Blah { + f1: U, + #[pin] + f2: T, +} + +unsafe impl UnsafeUnpin for Blah {} + +assert_unpin!(Blah<(), ()>); +assert_unpin!(Blah<(), PhantomPinned>); +assert_not_unpin!(Blah); +assert_not_unpin!(Blah); + +#[pin_project(UnsafeUnpin)] +struct OverlappingLifetimeNames<'pin, T, U> { + #[pin] + f1: U, + #[pin] + f2: Option, + f3: &'pin (), +} + +unsafe impl UnsafeUnpin for OverlappingLifetimeNames<'_, T, U> {} + +assert_unpin!(OverlappingLifetimeNames<'_, (), ()>); +assert_not_unpin!(OverlappingLifetimeNames<'_, PhantomPinned, ()>); +assert_not_unpin!(OverlappingLifetimeNames<'_, (), PhantomPinned>); +assert_not_unpin!(OverlappingLifetimeNames<'_, PhantomPinned, PhantomPinned>); + +#[test] +fn trivial_bounds() { + #[pin_project(UnsafeUnpin)] + pub struct NotImplementUnsafUnpin { + #[pin] + f: PhantomPinned, + } + + assert_not_unpin!(NotImplementUnsafUnpin); +} -- 2.7.4