├── tools └── .tidy-check-license-headers ├── tests ├── ui │ ├── .rustfmt.toml │ ├── pin_project │ │ ├── unpin_sneaky.stderr │ │ ├── unpin_sneaky.rs │ │ ├── project_replace_unsized.rs │ │ ├── packed_sneaky-2.rs │ │ ├── packed_sneaky-4.rs │ │ ├── overlapping_unpin_struct.rs │ │ ├── project_replace_unsized_fn_params.rs │ │ ├── packed_sneaky-2.stderr │ │ ├── add-pinned-field.rs │ │ ├── unaligned_references.rs │ │ ├── override-priv-mod.stderr │ │ ├── add-attr-to-struct.rs │ │ ├── negative_impls_stable.rs │ │ ├── negative_impls_stable.stderr │ │ ├── packed-enum.rs │ │ ├── conflict-drop.rs │ │ ├── impl-unsafe-unpin.rs │ │ ├── safe_packed_borrows.rs │ │ ├── packed_sneaky-3.rs │ │ ├── add-attr-to-struct.stderr │ │ ├── remove-attr-from-field.rs │ │ ├── packed.rs │ │ ├── packed-name-value.rs │ │ ├── conflict-drop.stderr │ │ ├── conflict-unpin.rs │ │ ├── packed.stderr │ │ ├── packed_sneaky-1.stderr │ │ ├── remove-attr-from-field.stderr │ │ ├── import_unnamed.rs │ │ ├── packed_sneaky-1.rs │ │ ├── packed-name-value.stderr │ │ ├── override-priv-mod.rs │ │ ├── remove-attr-from-struct.rs │ │ ├── packed-enum.stderr │ │ ├── overlapping_unpin_struct.stderr │ │ ├── packed_sneaky-3.stderr │ │ ├── unaligned_references.stderr │ │ ├── packed_sneaky-4.stderr │ │ ├── import_unnamed.stderr │ │ ├── visibility.rs │ │ ├── conflict-unpin.stderr │ │ ├── impl-unsafe-unpin.stderr │ │ ├── visibility.stderr │ │ ├── safe_packed_borrows.stderr │ │ └── add-pinned-field.stderr │ ├── pinned_drop │ │ ├── forget-pinned-drop-impl.rs │ │ ├── pinned-drop-no-attr-arg.stderr │ │ ├── pinned-drop-no-attr-arg.rs │ │ ├── call-drop-inner.rs │ │ ├── forget-pinned-drop-impl.stderr │ │ ├── unsafe-call.rs │ │ ├── invalid-self.rs │ │ ├── unsafe-call.stderr │ │ ├── conditional-drop-impl.rs │ │ ├── call-drop-inner.stderr │ │ ├── invalid-self.stderr │ │ ├── self.rs │ │ ├── conditional-drop-impl.stderr │ │ └── self.stderr │ ├── cfg │ │ ├── packed_sneaky.stderr │ │ ├── packed_sneaky-span-issue-1.stderr │ │ ├── packed_sneaky-span-issue-2.stderr │ │ ├── unsupported.rs │ │ ├── cfg_attr-resolve.rs │ │ ├── cfg_attr-resolve.stderr │ │ ├── unsupported.stderr │ │ ├── packed_sneaky-span-issue-1.rs │ │ ├── packed_sneaky-span-issue-2.rs │ │ ├── packed_sneaky.rs │ │ ├── cfg_attr-type-mismatch.rs │ │ └── cfg_attr-type-mismatch.stderr │ ├── unstable-features │ │ ├── README.md │ │ ├── marker_trait_attr-feature-gate.rs │ │ ├── marker_trait_attr.stderr │ │ ├── marker_trait_attr-feature-gate.stderr │ │ ├── negative_impls.stderr │ │ ├── negative_impls.rs │ │ ├── marker_trait_attr.rs │ │ ├── trivial_bounds.stderr │ │ ├── trivial_bounds.rs │ │ ├── trivial_bounds-feature-gate.rs │ │ └── trivial_bounds-feature-gate.stderr │ ├── not_unpin │ │ ├── negative_impls_stable.stderr │ │ ├── negative_impls_stable.rs │ │ ├── conflict-unpin.rs │ │ ├── impl-unsafe-unpin.rs │ │ ├── conflict-unpin.stderr │ │ └── impl-unsafe-unpin.stderr │ └── unsafe_unpin │ │ ├── negative_impls_stable.stderr │ │ ├── conflict-unpin.rs │ │ ├── negative_impls_stable.rs │ │ └── conflict-unpin.stderr ├── expand │ ├── .rustfmt.toml │ ├── default │ │ ├── tuple_struct.rs │ │ ├── struct.rs │ │ ├── enum.rs │ │ ├── tuple_struct.expanded.rs │ │ └── struct.expanded.rs │ ├── naming │ │ ├── tuple_struct-none.rs │ │ ├── tuple_struct-mut.rs │ │ ├── tuple_struct-ref.rs │ │ ├── tuple_struct-own.rs │ │ ├── struct-none.rs │ │ ├── tuple_struct-all.rs │ │ ├── struct-mut.rs │ │ ├── struct-ref.rs │ │ ├── struct-own.rs │ │ ├── struct-all.rs │ │ ├── enum-none.rs │ │ ├── enum-mut.rs │ │ ├── enum-ref.rs │ │ ├── enum-own.rs │ │ ├── enum-all.rs │ │ ├── enum-none.expanded.rs │ │ ├── enum-mut.expanded.rs │ │ ├── tuple_struct-none.expanded.rs │ │ ├── enum-ref.expanded.rs │ │ ├── struct-none.expanded.rs │ │ └── tuple_struct-mut.expanded.rs │ ├── pub │ │ ├── tuple_struct.rs │ │ ├── struct.rs │ │ ├── enum.rs │ │ ├── tuple_struct.expanded.rs │ │ └── struct.expanded.rs │ ├── not_unpin │ │ ├── tuple_struct.rs │ │ ├── struct.rs │ │ ├── enum.rs │ │ ├── tuple_struct.expanded.rs │ │ └── struct.expanded.rs │ ├── project_replace │ │ ├── tuple_struct.rs │ │ ├── struct.rs │ │ └── enum.rs │ ├── multifields │ │ ├── tuple_struct.rs │ │ ├── struct.rs │ │ └── enum.rs │ ├── unsafe_unpin │ │ ├── tuple_struct.rs │ │ ├── struct.rs │ │ ├── enum.rs │ │ ├── tuple_struct.expanded.rs │ │ └── struct.expanded.rs │ └── pinned_drop │ │ ├── tuple_struct.rs │ │ ├── struct.rs │ │ └── enum.rs ├── no-std │ ├── Cargo.toml │ └── lib.rs ├── rust-2015 │ ├── Cargo.toml │ └── lib.rs ├── lint │ └── Cargo.toml ├── expandtest.rs ├── compiletest.rs ├── no-core │ ├── Cargo.toml │ ├── build.rs │ └── lib.rs ├── auxiliary │ ├── mod.rs │ └── macro │ │ ├── Cargo.toml │ │ └── lib.rs ├── run-pass │ └── private_in_public-enum.rs ├── include │ └── basic.rs ├── unsafe_unpin.rs ├── repr_packed.rs └── proper_unpin.rs ├── .gitattributes ├── .git-blame-ignore-revs ├── .github ├── .cspell │ ├── rust-dependencies.txt │ └── project-dictionary.txt ├── dependabot.yml ├── zizmor.yml └── workflows │ ├── release.yml │ └── ci.yml ├── .taplo.toml ├── .gitignore ├── examples ├── enum-default.rs ├── struct-default.rs ├── project_replace.rs ├── unsafe_unpin.rs ├── not_unpin.rs ├── pinned_drop.rs ├── README.md ├── enum-default-expanded.rs └── unsafe_unpin-expanded.rs ├── .clippy.toml ├── .markdownlint-cli2.yaml ├── pin-project-internal ├── src │ ├── error.rs │ └── pin_project │ │ ├── mod.rs │ │ └── attribute.rs ├── Cargo.toml └── LICENSE-MIT ├── .editorconfig ├── .deny.toml ├── LICENSE-MIT ├── .shellcheckrc ├── .rustfmt.toml ├── DEVELOPMENT.md ├── .cspell.json └── README.md /tools/.tidy-check-license-headers: -------------------------------------------------------------------------------- 1 | git ls-files 2 | -------------------------------------------------------------------------------- /tests/ui/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | disable_all_formatting = true 2 | -------------------------------------------------------------------------------- /tests/expand/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | disable_all_formatting = true 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | tools/tidy.sh linguist-detectable=false 3 | .github/.cspell/rust-dependencies.txt linguist-generated 4 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # Change indent size of shell script files to match scripts in CI config 2 | ee924ee18ec73eea60a8672e1f68c1272161cdac 3 | -------------------------------------------------------------------------------- /.github/.cspell/rust-dependencies.txt: -------------------------------------------------------------------------------- 1 | # This file is @generated by tidy.sh. 2 | # It is not intended for manual editing. 3 | 4 | macrotest 5 | rustversion 6 | trybuild 7 | -------------------------------------------------------------------------------- /tests/expand/default/tuple_struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project] 6 | struct TupleStruct(#[pin] T, U); 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /tests/expand/naming/tuple_struct-none.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project] 6 | struct TupleStruct(#[pin] T, U); 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /tests/expand/pub/tuple_struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project] 6 | pub struct TupleStruct(#[pin] pub T, pub U); 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /tests/expand/not_unpin/tuple_struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(!Unpin)] 6 | struct TupleStruct(#[pin] T, U); 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /.github/.cspell/project-dictionary.txt: -------------------------------------------------------------------------------- 1 | compiletest 2 | elidable 3 | expandtest 4 | HRTB 5 | multifields 6 | overindented 7 | projectable 8 | qself 9 | reborrow 10 | respan 11 | respanned 12 | subpat 13 | unsafeunpin 14 | -------------------------------------------------------------------------------- /tests/expand/naming/tuple_struct-mut.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project = Proj)] 6 | struct TupleStruct(#[pin] T, U); 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /tests/expand/naming/tuple_struct-ref.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project_ref = ProjRef)] 6 | struct TupleStruct(#[pin] T, U); 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /tests/expand/project_replace/tuple_struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project_replace)] 6 | struct TupleStruct(#[pin] T, U); 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /tests/expand/multifields/tuple_struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project_replace)] 6 | struct TupleStruct(#[pin] T, #[pin] T, U, U); 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /tests/expand/naming/tuple_struct-own.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project_replace = ProjOwn)] 6 | struct TupleStruct(#[pin] T, U); 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /tests/ui/pin_project/unpin_sneaky.stderr: -------------------------------------------------------------------------------- 1 | error[E0425]: cannot find type `__S` in this scope 2 | --> tests/ui/pin_project/unpin_sneaky.rs:11:16 3 | | 4 | 11 | impl Unpin for __S {} //~ ERROR E0412,E0321 5 | | ^^^ not found in this scope 6 | -------------------------------------------------------------------------------- /tests/expand/default/struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project] 6 | struct Struct { 7 | #[pin] 8 | pinned: T, 9 | unpinned: U, 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /tests/expand/naming/struct-none.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project] 6 | struct Struct { 7 | #[pin] 8 | pinned: T, 9 | unpinned: U, 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /tests/expand/pub/struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project] 6 | pub struct Struct { 7 | #[pin] 8 | pub pinned: T, 9 | pub unpinned: U, 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /tests/no-std/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "no-std" 3 | version = "0.0.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [lib] 8 | path = "lib.rs" 9 | 10 | [dependencies] 11 | pin-project = { path = "../.." } 12 | 13 | [lints] 14 | workspace = true 15 | -------------------------------------------------------------------------------- /tests/expand/not_unpin/struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(!Unpin)] 6 | struct Struct { 7 | #[pin] 8 | pinned: T, 9 | unpinned: U, 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /tests/rust-2015/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-2015" 3 | version = "0.0.0" 4 | edition = "2015" 5 | publish = false 6 | 7 | [lib] 8 | path = "lib.rs" 9 | 10 | [dependencies] 11 | pin-project = { path = "../.." } 12 | 13 | [lints] 14 | workspace = true 15 | -------------------------------------------------------------------------------- /tests/ui/pinned_drop/forget-pinned-drop-impl.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(PinnedDrop)] //~ ERROR E0277 6 | struct Struct { 7 | #[pin] 8 | f: u8, 9 | } 10 | 11 | fn main() {} 12 | -------------------------------------------------------------------------------- /.taplo.toml: -------------------------------------------------------------------------------- 1 | # Taplo configuration 2 | # https://taplo.tamasfe.dev/configuration/formatter-options.html 3 | 4 | [formatting] 5 | align_comments = false 6 | allowed_blank_lines = 1 7 | array_auto_collapse = false 8 | array_auto_expand = false 9 | indent_string = " " 10 | -------------------------------------------------------------------------------- /tests/expand/naming/tuple_struct-all.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project = Proj, project_ref = ProjRef, project_replace = ProjOwn)] 6 | struct TupleStruct(#[pin] T, U); 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | 4 | # For platform and editor specific settings, it is recommended to add to 5 | # a global .gitignore file. 6 | # Refs: https://docs.github.com/en/github/using-git/ignoring-files#configuring-ignored-files-for-all-repositories-on-your-computer 7 | -------------------------------------------------------------------------------- /tests/expand/naming/struct-mut.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project = Proj)] 6 | struct Struct { 7 | #[pin] 8 | pinned: T, 9 | unpinned: U, 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /tests/expand/naming/struct-ref.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project_ref = ProjRef)] 6 | struct Struct { 7 | #[pin] 8 | pinned: T, 9 | unpinned: U, 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /tests/expand/project_replace/struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project_replace)] 6 | struct Struct { 7 | #[pin] 8 | pinned: T, 9 | unpinned: U, 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /tests/ui/pin_project/unpin_sneaky.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project] 6 | struct S { 7 | #[pin] 8 | f: u8, 9 | } 10 | 11 | impl Unpin for __S {} //~ ERROR E0412,E0321 12 | 13 | fn main() {} 14 | -------------------------------------------------------------------------------- /tests/expand/naming/struct-own.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project_replace = ProjOwn)] 6 | struct Struct { 7 | #[pin] 8 | pinned: T, 9 | unpinned: U, 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /tests/lint/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lint" 3 | version = "0.0.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [lib] 8 | path = "lib.rs" 9 | 10 | [dependencies] 11 | pin-project = { path = "../.." } 12 | 13 | [lints] 14 | # Set at the crate root. 15 | # workspace = true 16 | -------------------------------------------------------------------------------- /tests/ui/cfg/packed_sneaky.stderr: -------------------------------------------------------------------------------- 1 | error: #[pin_project] attribute may not be used on #[repr(packed)] types 2 | --> tests/ui/cfg/packed_sneaky.rs:8:27 3 | | 4 | 8 | #[hidden_repr_cfg_not_any(packed)] //~ ERROR may not be used on #[repr(packed)] types 5 | | ^^^^^^ 6 | -------------------------------------------------------------------------------- /tests/expandtest.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | #![cfg(not(miri))] 4 | 5 | #[rustversion::attr(not(nightly), ignore)] 6 | #[test] 7 | fn expandtest() { 8 | let args = &["--all-features"]; 9 | macrotest::expand_args("tests/expand/**/*.rs", args); 10 | } 11 | -------------------------------------------------------------------------------- /tests/ui/cfg/packed_sneaky-span-issue-1.stderr: -------------------------------------------------------------------------------- 1 | error: #[pin_project] attribute may not be used on #[repr(packed)] types 2 | --> tests/ui/cfg/packed_sneaky-span-issue-1.rs:7:15 3 | | 4 | 7 | #[hidden_repr(packed)] //~ ERROR may not be used on #[repr(packed)] types 5 | | ^^^^^^ 6 | -------------------------------------------------------------------------------- /tests/ui/cfg/packed_sneaky-span-issue-2.stderr: -------------------------------------------------------------------------------- 1 | error: #[pin_project] attribute may not be used on #[repr(packed)] types 2 | --> tests/ui/cfg/packed_sneaky-span-issue-2.rs:7:15 3 | | 4 | 7 | #[hidden_repr(packed)] //~ ERROR may not be used on #[repr(packed)] types 5 | | ^^^^^^ 6 | -------------------------------------------------------------------------------- /tests/ui/cfg/unsupported.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project] 6 | struct S { 7 | //~^ ERROR may not be used on structs with zero fields 8 | #[cfg(any())] 9 | #[pin] 10 | f: u8, 11 | } 12 | 13 | fn main() {} 14 | -------------------------------------------------------------------------------- /tests/ui/unstable-features/README.md: -------------------------------------------------------------------------------- 1 | # UI tests for unstable features 2 | 3 | These tests check how the guarantees and features provided by pin-project 4 | interact with unstable language features. 5 | 6 | The names of the files contained in this directory need to begin with the name 7 | of the feature. 8 | -------------------------------------------------------------------------------- /tests/compiletest.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | #![cfg(not(miri))] 4 | 5 | #[rustversion::attr(not(nightly), ignore)] 6 | #[test] 7 | fn ui() { 8 | let t = trybuild::TestCases::new(); 9 | t.compile_fail("tests/ui/**/*.rs"); 10 | t.pass("tests/run-pass/**/*.rs"); 11 | } 12 | -------------------------------------------------------------------------------- /tests/expand/unsafe_unpin/tuple_struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::{pin_project, UnsafeUnpin}; 4 | 5 | #[pin_project(UnsafeUnpin)] 6 | struct TupleStruct(#[pin] T, U); 7 | 8 | unsafe impl UnsafeUnpin for TupleStruct {} 9 | 10 | fn main() {} 11 | -------------------------------------------------------------------------------- /tests/expand/naming/struct-all.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project = Proj, project_ref = ProjRef, project_replace = ProjOwn)] 6 | struct Struct { 7 | #[pin] 8 | pinned: T, 9 | unpinned: U, 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /tests/ui/cfg/cfg_attr-resolve.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use std::pin::Pin; 4 | 5 | #[cfg_attr(any(), pin_project::pin_project)] 6 | struct Foo { 7 | f: T, 8 | } 9 | 10 | fn main() { 11 | let mut x = Foo { f: 0_u8 }; 12 | let _ = Pin::new(&mut x).project(); //~ ERROR E0599 13 | } 14 | -------------------------------------------------------------------------------- /tests/expand/multifields/struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project_replace)] 6 | struct Struct { 7 | #[pin] 8 | pinned1: T, 9 | #[pin] 10 | pinned2: T, 11 | unpinned1: U, 12 | unpinned2: U, 13 | } 14 | 15 | fn main() {} 16 | -------------------------------------------------------------------------------- /tests/ui/cfg/cfg_attr-resolve.stderr: -------------------------------------------------------------------------------- 1 | error[E0599]: no method named `project` found for struct `Pin<&mut Foo>` in the current scope 2 | --> tests/ui/cfg/cfg_attr-resolve.rs:12:30 3 | | 4 | 12 | let _ = Pin::new(&mut x).project(); //~ ERROR E0599 5 | | ^^^^^^^ method not found in `Pin<&mut Foo>` 6 | -------------------------------------------------------------------------------- /tests/expand/naming/enum-none.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project] 6 | enum Enum { 7 | Struct { 8 | #[pin] 9 | pinned: T, 10 | unpinned: U, 11 | }, 12 | Tuple(#[pin] T, U), 13 | Unit, 14 | } 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /examples/enum-default.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // See ./enum-default-expanded.rs for generated code. 4 | 5 | #![allow(dead_code)] 6 | 7 | use pin_project::pin_project; 8 | 9 | #[pin_project(project = EnumProj)] 10 | enum Enum { 11 | Pinned(#[pin] T), 12 | Unpinned(U), 13 | } 14 | 15 | fn main() {} 16 | -------------------------------------------------------------------------------- /examples/struct-default.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // See ./struct-default-expanded.rs for generated code. 4 | 5 | #![allow(dead_code)] 6 | 7 | use pin_project::pin_project; 8 | 9 | #[pin_project] 10 | struct Struct { 11 | #[pin] 12 | pinned: T, 13 | unpinned: U, 14 | } 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /tests/expand/naming/enum-mut.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project = Proj)] 6 | enum Enum { 7 | Struct { 8 | #[pin] 9 | pinned: T, 10 | unpinned: U, 11 | }, 12 | Tuple(#[pin] T, U), 13 | Unit, 14 | } 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /tests/expand/unsafe_unpin/struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::{pin_project, UnsafeUnpin}; 4 | 5 | #[pin_project(UnsafeUnpin)] 6 | struct Struct { 7 | #[pin] 8 | pinned: T, 9 | unpinned: U, 10 | } 11 | 12 | unsafe impl UnsafeUnpin for Struct {} 13 | 14 | fn main() {} 15 | -------------------------------------------------------------------------------- /tests/no-core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "no-core" 3 | version = "0.0.0" 4 | edition = "2021" 5 | rust-version = "1.68" # Prevent clippy from suggesting a code that requires a new version. 6 | publish = false 7 | 8 | [lib] 9 | path = "lib.rs" 10 | 11 | [dependencies] 12 | pin-project = { path = "../.." } 13 | 14 | [lints] 15 | workspace = true 16 | -------------------------------------------------------------------------------- /tests/expand/naming/enum-ref.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project_ref = ProjRef)] 6 | enum Enum { 7 | Struct { 8 | #[pin] 9 | pinned: T, 10 | unpinned: U, 11 | }, 12 | Tuple(#[pin] T, U), 13 | Unit, 14 | } 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /examples/project_replace.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // See ./struct-default-expanded.rs for generated code. 4 | 5 | #![allow(dead_code)] 6 | 7 | use pin_project::pin_project; 8 | 9 | #[pin_project(project_replace)] 10 | struct Struct { 11 | #[pin] 12 | pinned: T, 13 | unpinned: U, 14 | } 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /tests/expand/naming/enum-own.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project_replace = ProjOwn)] 6 | enum Enum { 7 | Struct { 8 | #[pin] 9 | pinned: T, 10 | unpinned: U, 11 | }, 12 | Tuple(#[pin] T, U), 13 | Unit, 14 | } 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /tests/ui/pin_project/project_replace_unsized.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project_replace)] //~ ERROR E0277 6 | struct Struct { 7 | f: T, 8 | } 9 | 10 | #[pin_project(project_replace)] //~ ERROR E0277 11 | struct TupleStruct(T); 12 | 13 | fn main() {} 14 | -------------------------------------------------------------------------------- /tests/expand/project_replace/enum.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project_replace = EnumProjOwn)] 6 | enum Enum { 7 | Struct { 8 | #[pin] 9 | pinned: T, 10 | unpinned: U, 11 | }, 12 | Tuple(#[pin] T, U), 13 | Unit, 14 | } 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /tests/ui/cfg/unsupported.stderr: -------------------------------------------------------------------------------- 1 | error: #[pin_project] attribute may not be used on structs with zero fields 2 | --> tests/ui/cfg/unsupported.rs:6:10 3 | | 4 | 6 | struct S { 5 | | __________^ 6 | 7 | | //~^ ERROR may not be used on structs with zero fields 7 | 8 | | #[cfg(any())] 8 | 9 | | #[pin] 9 | 10 | | f: u8, 10 | 11 | | } 11 | | |_^ 12 | -------------------------------------------------------------------------------- /tests/ui/pin_project/packed_sneaky-2.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use auxiliary_macro::hidden_repr_macro; 4 | use pin_project::pin_project; 5 | 6 | hidden_repr_macro! { //~ ERROR may not be used on #[repr(packed)] types 7 | #[pin_project] 8 | struct B { 9 | #[pin] 10 | f: u32, 11 | } 12 | } 13 | 14 | fn main() {} 15 | -------------------------------------------------------------------------------- /tests/ui/pinned_drop/pinned-drop-no-attr-arg.stderr: -------------------------------------------------------------------------------- 1 | error[E0119]: conflicting implementations of trait `PinnedDrop` for type `S` 2 | --> tests/ui/pinned_drop/pinned-drop-no-attr-arg.rs:14:1 3 | | 4 | 7 | #[pin_project] 5 | | -------------- first implementation here 6 | ... 7 | 14 | impl PinnedDrop for S { 8 | | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S` 9 | -------------------------------------------------------------------------------- /tests/expand/default/enum.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project = EnumProj, project_ref = EnumProjRef)] 6 | enum Enum { 7 | Struct { 8 | #[pin] 9 | pinned: T, 10 | unpinned: U, 11 | }, 12 | Tuple(#[pin] T, U), 13 | Unit, 14 | } 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /tests/expand/pub/enum.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project = EnumProj, project_ref = EnumProjRef)] 6 | pub enum Enum { 7 | Struct { 8 | #[pin] 9 | pinned: T, 10 | unpinned: U, 11 | }, 12 | Tuple(#[pin] T, U), 13 | Unit, 14 | } 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: / 5 | schedule: 6 | interval: daily 7 | commit-message: 8 | prefix: '' 9 | labels: [] 10 | - package-ecosystem: github-actions 11 | directory: / 12 | schedule: 13 | interval: daily 14 | commit-message: 15 | prefix: '' 16 | labels: [] 17 | -------------------------------------------------------------------------------- /tests/expand/not_unpin/enum.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(!Unpin, project = EnumProj, project_ref = EnumProjRef)] 6 | enum Enum { 7 | Struct { 8 | #[pin] 9 | pinned: T, 10 | unpinned: U, 11 | }, 12 | Tuple(#[pin] T, U), 13 | Unit, 14 | } 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /tests/auxiliary/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | #![allow(dead_code, unused_macros)] 4 | 5 | macro_rules! assert_unpin { 6 | ($ty:ty) => { 7 | static_assertions::assert_impl_all!($ty: Unpin); 8 | }; 9 | } 10 | macro_rules! assert_not_unpin { 11 | ($ty:ty) => { 12 | static_assertions::assert_not_impl_all!($ty: Unpin); 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /tests/ui/pin_project/packed_sneaky-4.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // https://github.com/taiki-e/pin-project/issues/342 4 | 5 | use auxiliary_macro::hidden_repr2; 6 | use pin_project::pin_project; 7 | 8 | #[pin_project] //~ ERROR reference to packed field is unaligned 9 | #[hidden_repr2] 10 | struct A { 11 | #[pin] 12 | f: u32, 13 | } 14 | 15 | fn main() {} 16 | -------------------------------------------------------------------------------- /tests/expand/naming/enum-all.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project = Proj, project_ref = ProjRef, project_replace = ProjOwn)] 6 | enum Enum { 7 | Struct { 8 | #[pin] 9 | pinned: T, 10 | unpinned: U, 11 | }, 12 | Tuple(#[pin] T, U), 13 | Unit, 14 | } 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /tests/ui/pinned_drop/pinned-drop-no-attr-arg.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use std::pin::Pin; 4 | 5 | use pin_project::{pin_project, pinned_drop}; 6 | 7 | #[pin_project] 8 | struct S { 9 | #[pin] 10 | f: u8, 11 | } 12 | 13 | #[pinned_drop] 14 | impl PinnedDrop for S { 15 | //~^ ERROR E0119 16 | fn drop(self: Pin<&mut Self>) {} 17 | } 18 | 19 | fn main() {} 20 | -------------------------------------------------------------------------------- /tests/ui/cfg/packed_sneaky-span-issue-1.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use auxiliary_macro::hidden_repr; 4 | use pin_project::pin_project; 5 | 6 | #[pin_project] 7 | #[hidden_repr(packed)] //~ ERROR may not be used on #[repr(packed)] types 8 | struct S { 9 | #[cfg(not(any()))] 10 | #[pin] 11 | f: u32, 12 | #[cfg(any())] 13 | #[pin] 14 | f: u8, 15 | } 16 | 17 | fn main() {} 18 | -------------------------------------------------------------------------------- /tests/ui/cfg/packed_sneaky-span-issue-2.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use auxiliary_macro::hidden_repr; 4 | use pin_project::pin_project; 5 | 6 | #[pin_project] 7 | #[hidden_repr(packed)] //~ ERROR may not be used on #[repr(packed)] types 8 | struct S { 9 | #[cfg(any())] 10 | #[pin] 11 | f: u32, 12 | #[cfg(not(any()))] 13 | #[pin] 14 | f: u8, 15 | } 16 | 17 | fn main() {} 18 | -------------------------------------------------------------------------------- /tests/ui/pinned_drop/call-drop-inner.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use std::pin::Pin; 4 | 5 | use pin_project::{pin_project, pinned_drop}; 6 | 7 | #[pin_project(PinnedDrop)] 8 | struct Struct { 9 | f: bool, 10 | } 11 | 12 | #[pinned_drop] 13 | impl PinnedDrop for Struct { 14 | fn drop(mut self: Pin<&mut Self>) { 15 | __drop_inner(__self); 16 | } 17 | } 18 | 19 | fn main() {} 20 | -------------------------------------------------------------------------------- /tests/expand/pinned_drop/tuple_struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use std::pin::Pin; 4 | 5 | use pin_project::{pin_project, pinned_drop}; 6 | 7 | #[pin_project(PinnedDrop)] 8 | struct TupleStruct(#[pin] T, U); 9 | 10 | #[pinned_drop] 11 | impl PinnedDrop for TupleStruct { 12 | fn drop(self: Pin<&mut Self>) { 13 | let _ = self; 14 | } 15 | } 16 | 17 | fn main() {} 18 | -------------------------------------------------------------------------------- /tests/ui/pin_project/overlapping_unpin_struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use std::marker::PhantomPinned; 4 | 5 | use pin_project::pin_project; 6 | 7 | #[pin_project] 8 | struct S { 9 | #[pin] 10 | f: T, 11 | } 12 | 13 | struct __S {} 14 | 15 | impl Unpin for __S {} 16 | 17 | fn is_unpin() {} 18 | 19 | fn main() { 20 | is_unpin::>(); //~ ERROR E0277 21 | } 22 | -------------------------------------------------------------------------------- /.clippy.toml: -------------------------------------------------------------------------------- 1 | # Clippy configuration 2 | # https://doc.rust-lang.org/nightly/clippy/lint_configuration.html 3 | 4 | allow-private-module-inception = true 5 | avoid-breaking-exported-api = false 6 | disallowed-names = [] 7 | disallowed-macros = [ 8 | { path = "std::dbg", reason = "it is okay to use during development, but please do not include it in main branch" }, 9 | ] 10 | disallowed-methods = [ 11 | ] 12 | disallowed-types = [ 13 | ] 14 | -------------------------------------------------------------------------------- /tests/ui/pin_project/project_replace_unsized_fn_params.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | #![allow(internal_features)] 4 | #![feature(unsized_fn_params)] 5 | 6 | use pin_project::pin_project; 7 | 8 | #[pin_project(project_replace)] //~ ERROR E0277 9 | struct Struct { 10 | f: T, 11 | } 12 | 13 | #[pin_project(project_replace)] //~ ERROR E0277 14 | struct TupleStruct(T); 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /tests/ui/cfg/packed_sneaky.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use auxiliary_macro::hidden_repr_cfg_not_any; 4 | use pin_project::pin_project; 5 | 6 | // `#[hidden_repr_cfg_not_any(packed)]` generates `#[cfg_attr(not(any()), repr(packed))]`. 7 | #[pin_project] 8 | #[hidden_repr_cfg_not_any(packed)] //~ ERROR may not be used on #[repr(packed)] types 9 | struct S { 10 | #[pin] 11 | f: u32, 12 | } 13 | 14 | fn main() {} 15 | -------------------------------------------------------------------------------- /.markdownlint-cli2.yaml: -------------------------------------------------------------------------------- 1 | # https://github.com/DavidAnson/markdownlint/blob/HEAD/doc/Rules.md 2 | config: 3 | line-length: false # MD013 4 | no-duplicate-heading: false # MD024 5 | no-blanks-blockquote: false # MD028 (this warns valid GFM alerts usage) 6 | no-inline-html: false # MD033 7 | no-emphasis-as-heading: false # MD036 8 | 9 | # https://github.com/DavidAnson/markdownlint-cli2#markdownlint-cli2jsonc 10 | noBanner: true 11 | noProgress: true 12 | -------------------------------------------------------------------------------- /examples/unsafe_unpin.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // See ./unsafe_unpin-expanded.rs for generated code. 4 | 5 | #![allow(dead_code, clippy::undocumented_unsafe_blocks)] 6 | 7 | use pin_project::{UnsafeUnpin, pin_project}; 8 | 9 | #[pin_project(UnsafeUnpin)] 10 | struct Struct { 11 | #[pin] 12 | pinned: T, 13 | unpinned: U, 14 | } 15 | 16 | unsafe impl UnsafeUnpin for Struct {} 17 | 18 | fn main() {} 19 | -------------------------------------------------------------------------------- /tests/expand/pinned_drop/struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use std::pin::Pin; 4 | 5 | use pin_project::{pin_project, pinned_drop}; 6 | 7 | #[pin_project(PinnedDrop)] 8 | struct Struct { 9 | #[pin] 10 | pinned: T, 11 | unpinned: U, 12 | } 13 | 14 | #[pinned_drop] 15 | impl PinnedDrop for Struct { 16 | fn drop(self: Pin<&mut Self>) { 17 | let _ = self; 18 | } 19 | } 20 | 21 | fn main() {} 22 | -------------------------------------------------------------------------------- /tests/expand/unsafe_unpin/enum.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::{pin_project, UnsafeUnpin}; 4 | 5 | #[pin_project(UnsafeUnpin, project = EnumProj, project_ref = EnumProjRef)] 6 | enum Enum { 7 | Struct { 8 | #[pin] 9 | pinned: T, 10 | unpinned: U, 11 | }, 12 | Tuple(#[pin] T, U), 13 | Unit, 14 | } 15 | 16 | unsafe impl UnsafeUnpin for Enum {} 17 | 18 | fn main() {} 19 | -------------------------------------------------------------------------------- /tests/ui/not_unpin/negative_impls_stable.stderr: -------------------------------------------------------------------------------- 1 | error[E0119]: conflicting implementations of trait `Unpin` for type `Foo` 2 | --> tests/ui/not_unpin/negative_impls_stable.rs:5:28 3 | | 4 | 5 | #[pin_project::pin_project(!Unpin)] 5 | | ^^^^^^ conflicting implementation for `Foo` 6 | ... 7 | 14 | impl Unpin for Foo {} 8 | | --------------------------------------- first implementation here 9 | -------------------------------------------------------------------------------- /.github/zizmor.yml: -------------------------------------------------------------------------------- 1 | # zizmor configuration 2 | # https://docs.zizmor.sh/configuration/ 3 | 4 | rules: 5 | dependabot-cooldown: { disable: true } # Useless unless hash-pin is forced by unpinned-uses. 6 | ref-confusion: { disable: true } # TODO: Old GHA didn't work without this pattern in some cases, but does it seem to be fixed? 7 | secrets-inherit: { disable: true } 8 | unpinned-uses: 9 | config: 10 | policies: 11 | taiki-e/*: any 12 | '*': ref-pin 13 | -------------------------------------------------------------------------------- /examples/not_unpin.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // See ./not_unpin-expanded.rs for generated code. 4 | 5 | #![allow(dead_code)] 6 | 7 | use pin_project::pin_project; 8 | 9 | #[pin_project(!Unpin)] 10 | struct Struct { 11 | #[pin] 12 | pinned: T, 13 | unpinned: U, 14 | } 15 | 16 | fn main() { 17 | fn _is_unpin() {} 18 | // _is_unpin::>(); //~ ERROR `std::marker::PhantomPinned` cannot be unpinned 19 | } 20 | -------------------------------------------------------------------------------- /tests/ui/pinned_drop/forget-pinned-drop-impl.stderr: -------------------------------------------------------------------------------- 1 | error[E0277]: the trait bound `Struct: PinnedDrop` is not satisfied 2 | --> tests/ui/pinned_drop/forget-pinned-drop-impl.rs:5:15 3 | | 4 | 5 | #[pin_project(PinnedDrop)] //~ ERROR E0277 5 | | ^^^^^^^^^^ unsatisfied trait bound 6 | | 7 | help: the trait `PinnedDrop` is not implemented for `Struct` 8 | --> tests/ui/pinned_drop/forget-pinned-drop-impl.rs:6:1 9 | | 10 | 6 | struct Struct { 11 | | ^^^^^^^^^^^^^ 12 | -------------------------------------------------------------------------------- /pin-project-internal/src/error.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | macro_rules! format_err { 4 | ($span:expr, $msg:expr $(,)?) => { 5 | syn::Error::new_spanned(&$span as &dyn quote::ToTokens, &$msg as &dyn std::fmt::Display) 6 | }; 7 | ($span:expr, $($tt:tt)*) => { 8 | format_err!($span, format!($($tt)*)) 9 | }; 10 | } 11 | 12 | macro_rules! bail { 13 | ($($tt:tt)*) => { 14 | return Err(format_err!($($tt)*)) 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /tests/ui/unsafe_unpin/negative_impls_stable.stderr: -------------------------------------------------------------------------------- 1 | error[E0119]: conflicting implementations of trait `Unpin` for type `Foo` 2 | --> tests/ui/unsafe_unpin/negative_impls_stable.rs:5:28 3 | | 4 | 5 | #[pin_project::pin_project(UnsafeUnpin)] 5 | | ^^^^^^^^^^^ conflicting implementation for `Foo` 6 | ... 7 | 16 | impl Unpin for Foo {} 8 | | --------------------------------------- first implementation here 9 | -------------------------------------------------------------------------------- /tests/expand/multifields/enum.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(project = EnumProj, project_ref = EnumProjRef, project_replace = EnumProjOwn)] 6 | enum Enum { 7 | Struct { 8 | #[pin] 9 | pinned1: T, 10 | #[pin] 11 | pinned2: T, 12 | unpinned1: U, 13 | unpinned2: U, 14 | }, 15 | Tuple(#[pin] T, #[pin] T, U, U), 16 | Unit, 17 | } 18 | 19 | fn main() {} 20 | -------------------------------------------------------------------------------- /tests/ui/pin_project/packed_sneaky-2.stderr: -------------------------------------------------------------------------------- 1 | error: #[pin_project] attribute may not be used on #[repr(packed)] types 2 | --> tests/ui/pin_project/packed_sneaky-2.rs:6:1 3 | | 4 | 6 | / hidden_repr_macro! { //~ ERROR may not be used on #[repr(packed)] types 5 | 7 | | #[pin_project] 6 | 8 | | struct B { 7 | 9 | | #[pin] 8 | ... | 9 | 12 | | } 10 | | |_^ 11 | | 12 | = note: this error originates in the macro `hidden_repr_macro` (in Nightly builds, run with -Z macro-backtrace for more info) 13 | -------------------------------------------------------------------------------- /tests/ui/pinned_drop/unsafe-call.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use std::pin::Pin; 4 | 5 | use pin_project::{pin_project, pinned_drop}; 6 | 7 | #[pin_project(PinnedDrop)] 8 | struct S { 9 | #[pin] 10 | f: u8, 11 | } 12 | 13 | #[pinned_drop] 14 | impl PinnedDrop for S { 15 | fn drop(self: Pin<&mut Self>) { 16 | self.project().f.get_unchecked_mut(); //~ ERROR call to unsafe function is unsafe and requires unsafe function or block [E0133] 17 | } 18 | } 19 | 20 | fn main() {} 21 | -------------------------------------------------------------------------------- /tests/ui/pin_project/add-pinned-field.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use auxiliary_macro::add_pinned_field; 4 | use pin_project::pin_project; 5 | 6 | fn is_unpin() {} 7 | 8 | #[pin_project] 9 | #[add_pinned_field] 10 | struct Foo { 11 | #[pin] 12 | f: u32, 13 | } 14 | 15 | #[add_pinned_field] 16 | #[pin_project] 17 | struct Bar { 18 | #[pin] 19 | f: u32, 20 | } 21 | 22 | fn main() { 23 | is_unpin::(); //~ ERROR E0277 24 | is_unpin::(); //~ ERROR E0277 25 | } 26 | -------------------------------------------------------------------------------- /tests/run-pass/private_in_public-enum.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // Even if allows private_in_public, these are errors. 4 | 5 | #![allow(private_interfaces, dead_code)] 6 | 7 | pub enum PublicEnum { 8 | V(PrivateEnum), //~ ERROR E0446 9 | } 10 | 11 | enum PrivateEnum { 12 | V(u8), 13 | } 14 | 15 | mod foo { 16 | pub(crate) enum CrateEnum { 17 | V(PrivateEnum), //~ ERROR E0446 18 | } 19 | 20 | enum PrivateEnum { 21 | V(u8), 22 | } 23 | } 24 | 25 | fn main() {} 26 | -------------------------------------------------------------------------------- /tests/auxiliary/macro/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pin-project-auxiliary-macro" 3 | version = "0.0.0" 4 | edition = "2021" 5 | rust-version = "1.68" # Prevent clippy from suggesting a code that requires a new version. 6 | publish = false 7 | 8 | [lib] 9 | name = "auxiliary_macro" 10 | path = "lib.rs" 11 | proc-macro = true 12 | 13 | [dependencies] 14 | proc-macro2 = "1" 15 | quote = "1" 16 | syn = { version = "2", default-features = false, features = ["parsing", "printing", "proc-macro", "full"] } 17 | 18 | [lints] 19 | workspace = true 20 | -------------------------------------------------------------------------------- /tests/ui/pin_project/unaligned_references.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // Refs: https://github.com/rust-lang/rust/issues/82523 4 | 5 | #[repr(packed)] 6 | struct Packed { 7 | f: u32, 8 | } 9 | 10 | #[repr(packed(2))] 11 | struct PackedN { 12 | f: u32, 13 | } 14 | 15 | fn main() { 16 | let a = Packed { f: 1 }; 17 | let _ = &a.f; //~ ERROR reference to packed field is unaligned 18 | 19 | let b = PackedN { f: 1 }; 20 | let _ = &b.f; //~ ERROR reference to packed field is unaligned 21 | } 22 | -------------------------------------------------------------------------------- /tests/ui/unstable-features/marker_trait_attr-feature-gate.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // Note: If you change this test, change 'marker_trait_attr.rs' at the same time. 4 | 5 | use std::marker::PhantomPinned; 6 | 7 | use pin_project::pin_project; 8 | 9 | #[pin_project] //~ ERROR E0119 10 | struct Struct { 11 | #[pin] 12 | f: T, 13 | } 14 | 15 | // unsound Unpin impl 16 | impl Unpin for Struct {} 17 | 18 | fn is_unpin() {} 19 | 20 | fn main() { 21 | is_unpin::>() 22 | } 23 | -------------------------------------------------------------------------------- /tests/ui/pin_project/override-priv-mod.stderr: -------------------------------------------------------------------------------- 1 | error[E0119]: conflicting implementations of trait `SMustNotImplDrop` for type `S` 2 | --> tests/ui/pin_project/override-priv-mod.rs:18:1 3 | | 4 | 18 | #[pin_project] //~ ERROR conflicting implementations of trait `_::FooMustNotImplDrop` 5 | | ^^^^^^^^^^^^^^ 6 | | | 7 | | first implementation here 8 | | conflicting implementation for `S` 9 | | 10 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 11 | -------------------------------------------------------------------------------- /examples/pinned_drop.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // See ./pinned_drop-expanded.rs for generated code. 4 | 5 | #![allow(dead_code)] 6 | 7 | use std::pin::Pin; 8 | 9 | use pin_project::{pin_project, pinned_drop}; 10 | 11 | #[pin_project(PinnedDrop)] 12 | pub struct Struct<'a, T> { 13 | was_dropped: &'a mut bool, 14 | #[pin] 15 | field: T, 16 | } 17 | 18 | #[pinned_drop] 19 | impl PinnedDrop for Struct<'_, T> { 20 | fn drop(self: Pin<&mut Self>) { 21 | **self.project().was_dropped = true; 22 | } 23 | } 24 | 25 | fn main() {} 26 | -------------------------------------------------------------------------------- /tests/expand/pinned_drop/enum.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use std::pin::Pin; 4 | 5 | use pin_project::{pin_project, pinned_drop}; 6 | 7 | #[pin_project(PinnedDrop, project = EnumProj, project_ref = EnumProjRef)] 8 | enum Enum { 9 | Struct { 10 | #[pin] 11 | pinned: T, 12 | unpinned: U, 13 | }, 14 | Tuple(#[pin] T, U), 15 | Unit, 16 | } 17 | 18 | #[pinned_drop] 19 | impl PinnedDrop for Enum { 20 | fn drop(self: Pin<&mut Self>) { 21 | let _ = self; 22 | } 23 | } 24 | 25 | fn main() {} 26 | -------------------------------------------------------------------------------- /tests/no-std/lib.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | #![no_std] 4 | 5 | // Check compatibility with no-std environment and Rust 2018. 6 | 7 | // This works in 2018 edition, but in 2015 edition it gives an error: 8 | // ```text 9 | // error[E0659]: `pin` is ambiguous (derive helper attribute vs any other name) 10 | // --> tests/rust-2015/../include/basic-safe-part.rs:3:1 11 | // | 12 | // 3 | #[pin_project] 13 | // | ^^^^^^^^^^^^^^ ambiguous name 14 | // | 15 | // ``` 16 | #[allow(unused_imports)] 17 | use pin_project as pin; 18 | 19 | include!("../include/basic.rs"); 20 | -------------------------------------------------------------------------------- /tests/ui/pin_project/add-attr-to-struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use std::marker::PhantomPinned; 4 | 5 | use auxiliary_macro::add_pin_attr; 6 | use pin_project::pin_project; 7 | 8 | #[pin_project] 9 | #[add_pin_attr(struct)] //~ ERROR expected attribute arguments in parentheses 10 | struct Foo { 11 | #[pin] 12 | f: PhantomPinned, 13 | } 14 | 15 | #[add_pin_attr(struct)] //~ ERROR #[pin] attribute may only be used on fields of structs or variants 16 | #[pin_project] 17 | struct Bar { 18 | #[pin] 19 | f: PhantomPinned, 20 | } 21 | 22 | fn main() {} 23 | -------------------------------------------------------------------------------- /tests/ui/unstable-features/marker_trait_attr.stderr: -------------------------------------------------------------------------------- 1 | error[E0119]: conflicting implementations of trait `Unpin` for type `Struct<_>` 2 | --> tests/ui/unstable-features/marker_trait_attr.rs:15:1 3 | | 4 | 15 | #[pin_project] //~ ERROR E0119 5 | | ^^^^^^^^^^^^^^ conflicting implementation for `Struct<_>` 6 | ... 7 | 22 | impl Unpin for Struct {} 8 | | --------------------------- first implementation here 9 | | 10 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig configuration 2 | # https://editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | end_of_line = lf 9 | indent_size = 4 10 | indent_style = space 11 | insert_final_newline = true 12 | trim_trailing_whitespace = true 13 | 14 | [*.{css,html,json,md,rb,sh,yml,yaml}] 15 | indent_size = 2 16 | 17 | [*.{js,yml,yaml}] 18 | quote_type = single 19 | 20 | [*.sh] 21 | # https://google.github.io/styleguide/shellguide.html#s5.3-pipelines 22 | binary_next_line = true 23 | # https://google.github.io/styleguide/shellguide.html#s5.5-case-statement 24 | switch_case_indent = true 25 | -------------------------------------------------------------------------------- /pin-project-internal/src/pin_project/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | mod args; 4 | mod attribute; 5 | mod derive; 6 | 7 | use proc_macro2::TokenStream; 8 | use syn::Error; 9 | 10 | /// The annotation for pinned type. 11 | const PIN: &str = "pin"; 12 | 13 | pub(crate) fn attribute(args: &TokenStream, input: TokenStream) -> TokenStream { 14 | attribute::parse_attribute(args, input).unwrap_or_else(Error::into_compile_error) 15 | } 16 | 17 | pub(crate) fn derive(input: TokenStream) -> TokenStream { 18 | derive::parse_derive(input).unwrap_or_else(Error::into_compile_error) 19 | } 20 | -------------------------------------------------------------------------------- /tests/ui/pin_project/negative_impls_stable.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // https://github.com/taiki-e/pin-project/issues/340#issuecomment-2428002670 4 | 5 | #[pin_project::pin_project] 6 | struct Foo { 7 | #[pin] 8 | pinned: Pinned, 9 | unpinned: Unpinned, 10 | } 11 | 12 | struct MyPhantomPinned(::core::marker::PhantomPinned); 13 | impl Unpin for MyPhantomPinned where for<'cursed> str: Sized {} 14 | impl Unpin for Foo {} 15 | 16 | fn is_unpin() {} 17 | 18 | fn main() { 19 | is_unpin::>() 20 | } 21 | -------------------------------------------------------------------------------- /tests/ui/pinned_drop/invalid-self.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // by-ref binding `ref (mut) self` and sub-patterns `@` are not allowed in receivers (rejected by rustc). 4 | 5 | use std::pin::Pin; 6 | 7 | struct S {} 8 | 9 | impl S { 10 | fn take_ref_self(ref self: Pin<&mut Self>) {} //~ ERROR expected identifier, found keyword `self` 11 | fn take_ref_mut_self(ref mut self: Pin<&mut Self>) {} //~ ERROR expected identifier, found keyword `self` 12 | 13 | fn self_subpat(self @ S {}: Self) {} //~ ERROR expected one of `)`, `,`, or `:`, found `@` 14 | } 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /tests/ui/not_unpin/negative_impls_stable.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // https://github.com/taiki-e/pin-project/issues/340#issuecomment-2428002670 4 | 5 | #[pin_project::pin_project(!Unpin)] 6 | struct Foo { 7 | #[pin] 8 | pinned: Pinned, 9 | unpinned: Unpinned, 10 | } 11 | 12 | struct MyPhantomPinned(::core::marker::PhantomPinned); 13 | impl Unpin for MyPhantomPinned where for<'cursed> str: Sized {} 14 | impl Unpin for Foo {} 15 | 16 | fn is_unpin() {} 17 | 18 | fn main() { 19 | is_unpin::>() 20 | } 21 | -------------------------------------------------------------------------------- /tests/ui/unstable-features/marker_trait_attr-feature-gate.stderr: -------------------------------------------------------------------------------- 1 | error[E0119]: conflicting implementations of trait `Unpin` for type `Struct<_>` 2 | --> tests/ui/unstable-features/marker_trait_attr-feature-gate.rs:9:1 3 | | 4 | 9 | #[pin_project] //~ ERROR E0119 5 | | ^^^^^^^^^^^^^^ conflicting implementation for `Struct<_>` 6 | ... 7 | 16 | impl Unpin for Struct {} 8 | | --------------------------- first implementation here 9 | | 10 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 11 | -------------------------------------------------------------------------------- /tests/rust-2015/lib.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | #![no_std] 4 | 5 | // Check compatibility with no-std environment and Rust 2015. 6 | 7 | extern crate pin_project; 8 | 9 | // This works in 2018 edition, but in 2015 edition it gives an error: 10 | // ```text 11 | // error[E0659]: `pin` is ambiguous (derive helper attribute vs any other name) 12 | // --> tests/rust-2015/../include/basic-safe-part.rs:3:1 13 | // | 14 | // 3 | #[pin_project] 15 | // | ^^^^^^^^^^^^^^ ambiguous name 16 | // | 17 | // ``` 18 | // #[allow(unused_imports)] 19 | // use pin_project as pin; 20 | 21 | include!("../include/basic.rs"); 22 | -------------------------------------------------------------------------------- /tests/no-core/build.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use std::{env, process::Command}; 4 | 5 | fn main() { 6 | println!("cargo:rerun-if-changed=build.rs"); 7 | println!("cargo:rustc-check-cfg=cfg(nightly)"); 8 | 9 | if is_nightly() { 10 | println!("cargo:rustc-cfg=nightly"); 11 | } 12 | } 13 | 14 | fn is_nightly() -> bool { 15 | env::var_os("RUSTC") 16 | .and_then(|rustc| Command::new(rustc).arg("--version").output().ok()) 17 | .and_then(|output| String::from_utf8(output.stdout).ok()) 18 | .map_or(false, |version| version.contains("nightly") || version.contains("dev")) 19 | } 20 | -------------------------------------------------------------------------------- /tests/ui/unstable-features/negative_impls.stderr: -------------------------------------------------------------------------------- 1 | error[E0119]: conflicting implementations of trait `Unpin` for type `Foo` 2 | --> tests/ui/unstable-features/negative_impls.rs:8:1 3 | | 4 | 8 | #[pin_project::pin_project] 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Foo` 6 | ... 7 | 17 | impl Unpin for Foo {} 8 | | --------------------------------------- first implementation here 9 | | 10 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 11 | -------------------------------------------------------------------------------- /tests/ui/pin_project/negative_impls_stable.stderr: -------------------------------------------------------------------------------- 1 | error[E0119]: conflicting implementations of trait `Unpin` for type `Foo` 2 | --> tests/ui/pin_project/negative_impls_stable.rs:5:1 3 | | 4 | 5 | #[pin_project::pin_project] 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Foo` 6 | ... 7 | 14 | impl Unpin for Foo {} 8 | | --------------------------------------- first implementation here 9 | | 10 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 11 | -------------------------------------------------------------------------------- /tests/ui/pin_project/packed-enum.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | // #[repr(packed)] cannot be apply on enums and will be rejected by rustc. 6 | // However, we should not rely on the behavior of rustc that rejects this. 7 | // https://github.com/taiki-e/pin-project/pull/324#discussion_r612388001 8 | 9 | #[repr(packed)] //~ ERROR E0517 10 | enum E1 { 11 | V(()), 12 | } 13 | 14 | #[pin_project] 15 | #[repr(packed)] //~ ERROR E0517 16 | enum E2 { 17 | V(()), 18 | } 19 | 20 | #[repr(packed)] //~ ERROR E0517 21 | #[pin_project] 22 | enum E3 { 23 | V(()), 24 | } 25 | 26 | fn main() {} 27 | -------------------------------------------------------------------------------- /tests/ui/pinned_drop/unsafe-call.stderr: -------------------------------------------------------------------------------- 1 | error[E0133]: call to unsafe function `Pin::<&'a mut T>::get_unchecked_mut` is unsafe and requires unsafe function or block 2 | --> tests/ui/pinned_drop/unsafe-call.rs:16:9 3 | | 4 | 13 | #[pinned_drop] 5 | | -------------- items do not inherit unsafety from separate enclosing items 6 | ... 7 | 16 | self.project().f.get_unchecked_mut(); //~ ERROR call to unsafe function is unsafe and requires unsafe function or block [E0133] 8 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function 9 | | 10 | = note: consult the function's documentation for information on how to avoid undefined behavior 11 | -------------------------------------------------------------------------------- /tests/ui/not_unpin/conflict-unpin.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(!Unpin)] //~ ERROR E0119 6 | struct Foo { 7 | #[pin] 8 | f1: T, 9 | f2: U, 10 | } 11 | 12 | impl Unpin for Foo where T: Unpin {} 13 | 14 | #[pin_project(!Unpin)] //~ ERROR E0119 15 | struct Bar { 16 | #[pin] 17 | f1: T, 18 | f2: U, 19 | } 20 | 21 | impl Unpin for Bar {} 22 | 23 | #[pin_project(!Unpin)] //~ ERROR E0119 24 | struct Baz { 25 | #[pin] 26 | f1: T, 27 | f2: U, 28 | } 29 | 30 | impl Unpin for Baz {} 31 | 32 | fn main() {} 33 | -------------------------------------------------------------------------------- /tests/ui/cfg/cfg_attr-type-mismatch.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use std::pin::Pin; 4 | 5 | use pin_project::pin_project; 6 | 7 | #[cfg_attr(not(any()), pin_project)] 8 | struct Foo { 9 | #[cfg_attr(any(), pin)] 10 | f: T, 11 | } 12 | 13 | #[cfg_attr(not(any()), pin_project)] 14 | struct Bar { 15 | #[cfg_attr(not(any()), pin)] 16 | f: T, 17 | } 18 | 19 | fn main() { 20 | let mut x = Foo { f: 0_u8 }; 21 | let x = Pin::new(&mut x).project(); 22 | let _: Pin<&mut u8> = x.f; //~ ERROR E0308 23 | 24 | let mut x = Bar { f: 0_u8 }; 25 | let x = Pin::new(&mut x).project(); 26 | let _: &mut u8 = x.f; //~ ERROR E0308 27 | } 28 | -------------------------------------------------------------------------------- /tests/ui/unsafe_unpin/conflict-unpin.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project(UnsafeUnpin)] //~ ERROR E0119 6 | struct Foo { 7 | #[pin] 8 | f1: T, 9 | f2: U, 10 | } 11 | 12 | impl Unpin for Foo where T: Unpin {} 13 | 14 | #[pin_project(UnsafeUnpin)] //~ ERROR E0119 15 | struct Bar { 16 | #[pin] 17 | f1: T, 18 | f2: U, 19 | } 20 | 21 | impl Unpin for Bar {} 22 | 23 | #[pin_project(UnsafeUnpin)] //~ ERROR E0119 24 | struct Baz { 25 | #[pin] 26 | f1: T, 27 | f2: U, 28 | } 29 | 30 | impl Unpin for Baz {} 31 | 32 | fn main() {} 33 | -------------------------------------------------------------------------------- /tests/ui/unstable-features/negative_impls.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | #![feature(negative_impls)] 4 | 5 | // https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/design.20meeting.3A.20backlog.20bonanza/near/269471299 6 | // https://github.com/taiki-e/pin-project/issues/340 7 | 8 | #[pin_project::pin_project] 9 | struct Foo { 10 | #[pin] 11 | pinned: Pinned, 12 | unpinned: Unpinned, 13 | } 14 | 15 | struct MyPhantomPinned {} 16 | impl !Unpin for MyPhantomPinned {} 17 | impl Unpin for Foo {} 18 | 19 | fn is_unpin() {} 20 | 21 | fn main() { 22 | is_unpin::>() 23 | } 24 | -------------------------------------------------------------------------------- /tests/ui/pinned_drop/conditional-drop-impl.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use std::pin::Pin; 4 | 5 | use pin_project::{pin_project, pinned_drop}; 6 | 7 | // In `Drop` impl, the implementor must specify the same requirement as type definition. 8 | 9 | struct DropImpl { 10 | f: T, 11 | } 12 | 13 | impl Drop for DropImpl { 14 | //~^ ERROR E0367 15 | fn drop(&mut self) {} 16 | } 17 | 18 | #[pin_project(PinnedDrop)] //~ ERROR E0277 19 | struct PinnedDropImpl { 20 | #[pin] 21 | f: T, 22 | } 23 | 24 | #[pinned_drop] 25 | impl PinnedDrop for PinnedDropImpl { 26 | fn drop(self: Pin<&mut Self>) {} 27 | } 28 | 29 | fn main() {} 30 | -------------------------------------------------------------------------------- /tests/ui/pin_project/conflict-drop.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use std::pin::Pin; 4 | 5 | use pin_project::{pin_project, pinned_drop}; 6 | 7 | #[pin_project] //~ ERROR E0119 8 | struct Foo { 9 | #[pin] 10 | f1: T, 11 | f2: U, 12 | } 13 | 14 | impl Drop for Foo { 15 | fn drop(&mut self) {} 16 | } 17 | 18 | #[pin_project(PinnedDrop)] //~ ERROR E0119 19 | struct Bar { 20 | #[pin] 21 | f1: T, 22 | f2: U, 23 | } 24 | 25 | #[pinned_drop] 26 | impl PinnedDrop for Bar { 27 | fn drop(self: Pin<&mut Self>) {} 28 | } 29 | 30 | impl Drop for Bar { 31 | fn drop(&mut self) {} 32 | } 33 | 34 | fn main() {} 35 | -------------------------------------------------------------------------------- /tests/ui/pin_project/impl-unsafe-unpin.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::{pin_project, UnsafeUnpin}; 4 | 5 | #[pin_project] //~ ERROR E0119 6 | struct Foo { 7 | #[pin] 8 | f1: T, 9 | f2: U, 10 | } 11 | 12 | unsafe impl UnsafeUnpin for Foo where T: Unpin {} 13 | 14 | #[pin_project] //~ ERROR E0119 15 | struct Bar { 16 | #[pin] 17 | f1: T, 18 | f2: U, 19 | } 20 | 21 | unsafe impl UnsafeUnpin for Bar {} 22 | 23 | #[pin_project] //~ ERROR E0119 24 | struct Baz { 25 | #[pin] 26 | f1: T, 27 | f2: U, 28 | } 29 | 30 | unsafe impl UnsafeUnpin for Baz {} 31 | 32 | fn main() {} 33 | -------------------------------------------------------------------------------- /tests/ui/pinned_drop/call-drop-inner.stderr: -------------------------------------------------------------------------------- 1 | error[E0061]: this function takes 0 arguments but 1 argument was supplied 2 | --> tests/ui/pinned_drop/call-drop-inner.rs:15:9 3 | | 4 | 15 | __drop_inner(__self); 5 | | ^^^^^^^^^^^^ ------ unexpected argument of type `Pin<&mut Struct>` 6 | | 7 | note: function defined here 8 | --> tests/ui/pinned_drop/call-drop-inner.rs:12:1 9 | | 10 | 12 | #[pinned_drop] 11 | | ^^^^^^^^^^^^^^ 12 | = note: this error originates in the attribute macro `pinned_drop` (in Nightly builds, run with -Z macro-backtrace for more info) 13 | help: remove the extra argument 14 | | 15 | 15 - __drop_inner(__self); 16 | 15 + __drop_inner(); 17 | | 18 | -------------------------------------------------------------------------------- /tests/ui/unsafe_unpin/negative_impls_stable.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // https://github.com/taiki-e/pin-project/issues/340#issuecomment-2428002670 4 | 5 | #[pin_project::pin_project(UnsafeUnpin)] 6 | struct Foo { 7 | #[pin] 8 | pinned: Pinned, 9 | unpinned: Unpinned, 10 | } 11 | 12 | unsafe impl pin_project::UnsafeUnpin for Foo {} 13 | 14 | struct MyPhantomPinned(::core::marker::PhantomPinned); 15 | impl Unpin for MyPhantomPinned where for<'cursed> str: Sized {} 16 | impl Unpin for Foo {} 17 | 18 | fn is_unpin() {} 19 | 20 | fn main() { 21 | is_unpin::>() 22 | } 23 | -------------------------------------------------------------------------------- /tests/ui/not_unpin/impl-unsafe-unpin.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::{pin_project, UnsafeUnpin}; 4 | 5 | #[pin_project(!Unpin)] //~ ERROR E0119 6 | struct Foo { 7 | #[pin] 8 | f1: T, 9 | f2: U, 10 | } 11 | 12 | unsafe impl UnsafeUnpin for Foo where T: Unpin {} 13 | 14 | #[pin_project(!Unpin)] //~ ERROR E0119 15 | struct Bar { 16 | #[pin] 17 | f1: T, 18 | f2: U, 19 | } 20 | 21 | unsafe impl UnsafeUnpin for Bar {} 22 | 23 | #[pin_project(!Unpin)] //~ ERROR E0119 24 | struct Baz { 25 | #[pin] 26 | f1: T, 27 | f2: U, 28 | } 29 | 30 | unsafe impl UnsafeUnpin for Baz {} 31 | 32 | fn main() {} 33 | -------------------------------------------------------------------------------- /tests/ui/pin_project/safe_packed_borrows.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | #![deny(renamed_and_removed_lints)] 4 | #![deny(safe_packed_borrows)] //~ ERROR has been renamed to `unaligned_references` 5 | 6 | // This lint was removed in https://github.com/rust-lang/rust/pull/82525 (nightly-2021-03-28). 7 | // Refs: 8 | // - https://github.com/rust-lang/rust/pull/82525 9 | // - https://github.com/rust-lang/rust/issues/46043 10 | 11 | #[repr(packed)] 12 | struct Packed { 13 | f: u32, 14 | } 15 | 16 | #[repr(packed(2))] 17 | struct PackedN { 18 | f: u32, 19 | } 20 | 21 | fn main() { 22 | let a = Packed { f: 1 }; 23 | let _ = &a.f; 24 | 25 | let b = PackedN { f: 1 }; 26 | let _ = &b.f; 27 | } 28 | -------------------------------------------------------------------------------- /tests/ui/pin_project/packed_sneaky-3.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use auxiliary_macro::{hidden_repr_macro, HiddenRepr}; 4 | use pin_project::pin_project; 5 | 6 | hidden_repr_macro! {} //~ ERROR expected item after attributes 7 | #[pin_project] 8 | struct S1 { 9 | #[pin] 10 | f: u32, 11 | } 12 | 13 | macro_rules! hidden_repr_macro2 { 14 | () => { 15 | #[repr(packed)] //~ ERROR expected item after attributes 16 | }; 17 | } 18 | 19 | hidden_repr_macro2! {} 20 | #[pin_project] 21 | struct S2 { 22 | #[pin] 23 | f: u32, 24 | } 25 | 26 | #[derive(HiddenRepr)] //~ ERROR expected item after attributes 27 | struct S3 {} 28 | #[pin_project] 29 | struct S4 { 30 | #[pin] 31 | f: u32, 32 | } 33 | 34 | fn main() {} 35 | -------------------------------------------------------------------------------- /tests/ui/unstable-features/marker_trait_attr.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // Note: If you change this test, change 'marker_trait_attr-feature-gate.rs' at the same time. 4 | 5 | // marker_trait_attr 6 | // Tracking issue: https://github.com/rust-lang/rust/issues/29864 7 | #![feature(marker_trait_attr)] 8 | 9 | // See https://github.com/taiki-e/pin-project/issues/105#issuecomment-535355974 10 | 11 | use std::marker::PhantomPinned; 12 | 13 | use pin_project::pin_project; 14 | 15 | #[pin_project] //~ ERROR E0119 16 | struct Struct { 17 | #[pin] 18 | f: T, 19 | } 20 | 21 | // unsound Unpin impl 22 | impl Unpin for Struct {} 23 | 24 | fn is_unpin() {} 25 | 26 | fn main() { 27 | is_unpin::>() 28 | } 29 | -------------------------------------------------------------------------------- /tests/ui/pin_project/add-attr-to-struct.stderr: -------------------------------------------------------------------------------- 1 | error: expected attribute arguments in parentheses: `pin(...)` 2 | --> tests/ui/pin_project/add-attr-to-struct.rs:9:1 3 | | 4 | 9 | #[add_pin_attr(struct)] //~ ERROR expected attribute arguments in parentheses 5 | | ^^^^^^^^^^^^^^^^^^^^^^^ 6 | | 7 | = note: this error originates in the attribute macro `add_pin_attr` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | 9 | error: #[pin] attribute may only be used on fields of structs or variants 10 | --> tests/ui/pin_project/add-attr-to-struct.rs:15:1 11 | | 12 | 15 | #[add_pin_attr(struct)] //~ ERROR #[pin] attribute may only be used on fields of structs or variants 13 | | ^^^^^^^^^^^^^^^^^^^^^^^ 14 | | 15 | = note: this error originates in the attribute macro `add_pin_attr` (in Nightly builds, run with -Z macro-backtrace for more info) 16 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | permissions: 4 | contents: read 5 | 6 | on: 7 | workflow_dispatch: 8 | inputs: 9 | version: 10 | description: Version to be increased 11 | required: true 12 | type: choice 13 | options: 14 | - patch 15 | - minor 16 | - major 17 | 18 | defaults: 19 | run: 20 | shell: bash --noprofile --norc -CeEuxo pipefail {0} 21 | 22 | jobs: 23 | release: 24 | if: github.repository_owner == 'taiki-e' 25 | uses: taiki-e/github-actions/.github/workflows/rust-release.yml@main 26 | permissions: 27 | contents: write # for taiki-e/create-gh-release-action 28 | id-token: write # for rust-lang/crates-io-auth-action 29 | secrets: inherit 30 | with: 31 | version: ${{ inputs.version }} 32 | crates: pin-project-internal,. 33 | -------------------------------------------------------------------------------- /tests/include/basic.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | include!("basic-safe-part.rs"); 4 | 5 | #[allow(unused_qualifications, clippy::absolute_paths, clippy::undocumented_unsafe_blocks)] 6 | unsafe impl 7 | ::pin_project::UnsafeUnpin for UnsafeUnpinStruct 8 | { 9 | } 10 | #[allow(unused_qualifications, clippy::absolute_paths, clippy::undocumented_unsafe_blocks)] 11 | unsafe impl 12 | ::pin_project::UnsafeUnpin for UnsafeUnpinTupleStruct 13 | { 14 | } 15 | #[allow(unused_qualifications, clippy::absolute_paths, clippy::undocumented_unsafe_blocks)] 16 | unsafe impl 17 | ::pin_project::UnsafeUnpin for UnsafeUnpinEnum 18 | { 19 | } 20 | -------------------------------------------------------------------------------- /tests/ui/pin_project/remove-attr-from-field.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use std::{marker::PhantomPinned, pin::Pin}; 4 | 5 | use auxiliary_macro::remove_attr; 6 | use pin_project::pin_project; 7 | 8 | fn is_unpin() {} 9 | 10 | #[pin_project] 11 | #[remove_attr(field_all)] 12 | struct A { 13 | #[pin] 14 | f: PhantomPinned, 15 | } 16 | 17 | #[remove_attr(field_all)] 18 | #[pin_project] 19 | struct B { 20 | #[pin] 21 | f: PhantomPinned, 22 | } 23 | 24 | fn main() { 25 | is_unpin::(); 26 | is_unpin::(); 27 | 28 | let mut x = A { f: PhantomPinned }; 29 | let x = Pin::new(&mut x).project(); 30 | let _: Pin<&mut PhantomPinned> = x.f; //~ ERROR E0308 31 | 32 | let mut x = B { f: PhantomPinned }; 33 | let x = Pin::new(&mut x).project(); 34 | let _: Pin<&mut PhantomPinned> = x.f; //~ ERROR E0308 35 | } 36 | -------------------------------------------------------------------------------- /tests/ui/pin_project/packed.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | #[pin_project] 6 | #[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] types 7 | struct Packed1 { 8 | #[pin] 9 | f: u8, 10 | } 11 | 12 | // Test putting 'repr' before the 'pin_project' attribute 13 | #[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] types 14 | #[pin_project] 15 | struct Packed2 { 16 | #[pin] 17 | f: u8, 18 | } 19 | 20 | #[pin_project] 21 | #[repr(packed(2))] //~ ERROR may not be used on #[repr(packed)] types 22 | struct PackedN1 { 23 | #[pin] 24 | f: u32, 25 | } 26 | 27 | // Test putting 'repr' before the 'pin_project' attribute 28 | #[repr(packed(2))] //~ ERROR may not be used on #[repr(packed)] types 29 | #[pin_project] 30 | struct PackedN2 { 31 | #[pin] 32 | f: u32, 33 | } 34 | 35 | fn main() {} 36 | -------------------------------------------------------------------------------- /tests/ui/pin_project/packed-name-value.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | // #[repr(packed = "")] is not valid format of #[repr(packed)] and will be 6 | // rejected by rustc. 7 | // However, we should not rely on the behavior of rustc that rejects this. 8 | // https://github.com/taiki-e/pin-project/pull/324#discussion_r612388001 9 | 10 | // https://github.com/taiki-e/pin-project/pull/324#discussion_r612388001 11 | // https://github.com/rust-lang/rust/issues/83921 12 | // #[repr(packed = "")] //~ ERROR E0552 13 | // struct S1 { 14 | // f: (), 15 | // } 16 | 17 | #[pin_project] 18 | #[repr(packed = "")] //~ ERROR attribute should not be name-value pair 19 | struct S2 { 20 | f: (), 21 | } 22 | 23 | #[repr(packed = "")] //~ ERROR attribute should not be name-value pair 24 | #[pin_project] 25 | struct S3 { 26 | f: (), 27 | } 28 | 29 | fn main() {} 30 | -------------------------------------------------------------------------------- /tests/ui/pin_project/conflict-drop.stderr: -------------------------------------------------------------------------------- 1 | error[E0119]: conflicting implementations of trait `Drop` for type `Bar<_, _>` 2 | --> tests/ui/pin_project/conflict-drop.rs:18:15 3 | | 4 | 18 | #[pin_project(PinnedDrop)] //~ ERROR E0119 5 | | ^^^^^^^^^^ conflicting implementation for `Bar<_, _>` 6 | ... 7 | 30 | impl Drop for Bar { 8 | | ----------------------------- first implementation here 9 | 10 | error[E0119]: conflicting implementations of trait `FooMustNotImplDrop` for type `Foo<_, _>` 11 | --> tests/ui/pin_project/conflict-drop.rs:7:1 12 | | 13 | 7 | #[pin_project] //~ ERROR E0119 14 | | ^^^^^^^^^^^^^^ 15 | | | 16 | | first implementation here 17 | | conflicting implementation for `Foo<_, _>` 18 | | 19 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 20 | -------------------------------------------------------------------------------- /tests/ui/pin_project/conflict-unpin.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use pin_project::pin_project; 4 | 5 | // The same implementation. 6 | 7 | #[pin_project] //~ ERROR E0119 8 | struct Foo { 9 | #[pin] 10 | f1: T, 11 | f2: U, 12 | } 13 | 14 | // conflicting implementations 15 | impl Unpin for Foo where T: Unpin {} // Conditional Unpin impl 16 | 17 | // The implementation that under different conditions. 18 | 19 | #[pin_project] //~ ERROR E0119 20 | struct Bar { 21 | #[pin] 22 | f1: T, 23 | f2: U, 24 | } 25 | 26 | // conflicting implementations 27 | impl Unpin for Bar {} // Non-conditional Unpin impl 28 | 29 | #[pin_project] //~ ERROR E0119 30 | struct Baz { 31 | #[pin] 32 | f1: T, 33 | f2: U, 34 | } 35 | 36 | // conflicting implementations 37 | impl Unpin for Baz {} // Conditional Unpin impl 38 | 39 | fn main() {} 40 | -------------------------------------------------------------------------------- /tests/ui/pin_project/packed.stderr: -------------------------------------------------------------------------------- 1 | error: #[pin_project] attribute may not be used on #[repr(packed)] types 2 | --> tests/ui/pin_project/packed.rs:6:8 3 | | 4 | 6 | #[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] types 5 | | ^^^^^^ 6 | 7 | error: #[pin_project] attribute may not be used on #[repr(packed)] types 8 | --> tests/ui/pin_project/packed.rs:13:8 9 | | 10 | 13 | #[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] types 11 | | ^^^^^^ 12 | 13 | error: #[pin_project] attribute may not be used on #[repr(packed)] types 14 | --> tests/ui/pin_project/packed.rs:21:8 15 | | 16 | 21 | #[repr(packed(2))] //~ ERROR may not be used on #[repr(packed)] types 17 | | ^^^^^^^^^ 18 | 19 | error: #[pin_project] attribute may not be used on #[repr(packed)] types 20 | --> tests/ui/pin_project/packed.rs:28:8 21 | | 22 | 28 | #[repr(packed(2))] //~ ERROR may not be used on #[repr(packed)] types 23 | | ^^^^^^^^^ 24 | -------------------------------------------------------------------------------- /pin-project-internal/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pin-project-internal" 3 | version = "1.1.10" #publish:version 4 | edition = "2021" 5 | # NB: Sync with rust-version field in other Cargo.toml files and msrv badge in README.md 6 | rust-version = "1.68" # For syn 7 | license = "Apache-2.0 OR MIT" 8 | repository = "https://github.com/taiki-e/pin-project" 9 | keywords = ["pin", "macros", "attribute"] 10 | categories = ["no-std", "no-std::no-alloc", "rust-patterns"] 11 | description = """ 12 | Implementation detail of the `pin-project` crate. 13 | """ 14 | 15 | [package.metadata.docs.rs] 16 | targets = ["x86_64-unknown-linux-gnu"] 17 | 18 | [lib] 19 | proc-macro = true 20 | 21 | [dependencies] 22 | proc-macro2 = "1.0.60" 23 | quote = "1.0.25" 24 | syn = { version = "2.0.1", default-features = false, features = ["parsing", "printing", "clone-impls", "proc-macro", "full", "visit-mut"] } 25 | 26 | [dev-dependencies] 27 | pin-project = { path = ".." } 28 | 29 | [lints] 30 | workspace = true 31 | -------------------------------------------------------------------------------- /tests/ui/cfg/cfg_attr-type-mismatch.stderr: -------------------------------------------------------------------------------- 1 | error[E0308]: mismatched types 2 | --> tests/ui/cfg/cfg_attr-type-mismatch.rs:22:27 3 | | 4 | 22 | let _: Pin<&mut u8> = x.f; //~ ERROR E0308 5 | | ------------ ^^^ expected `Pin<&mut u8>`, found `&mut u8` 6 | | | 7 | | expected due to this 8 | | 9 | = note: expected struct `Pin<&mut u8>` 10 | found mutable reference `&mut u8` 11 | 12 | error[E0308]: mismatched types 13 | --> tests/ui/cfg/cfg_attr-type-mismatch.rs:26:22 14 | | 15 | 26 | let _: &mut u8 = x.f; //~ ERROR E0308 16 | | ------- ^^^ expected `&mut u8`, found `Pin<&mut u8>` 17 | | | 18 | | expected due to this 19 | | 20 | = note: expected mutable reference `&mut u8` 21 | found struct `Pin<&mut u8>` 22 | help: consider mutably borrowing here 23 | | 24 | 26 | let _: &mut u8 = &mut x.f; //~ ERROR E0308 25 | | ++++ 26 | -------------------------------------------------------------------------------- /tests/ui/pin_project/packed_sneaky-1.stderr: -------------------------------------------------------------------------------- 1 | error: #[pin_project] attribute may not be used on #[repr(packed)] types 2 | --> tests/ui/pin_project/packed_sneaky-1.rs:9:15 3 | | 4 | 9 | #[hidden_repr(packed)] 5 | | ^^^^^^ 6 | 7 | error: #[pin_project] attribute may not be used on #[repr(packed)] types 8 | --> tests/ui/pin_project/packed_sneaky-1.rs:15:1 9 | | 10 | 15 | #[hidden_repr2] 11 | | ^^^^^^^^^^^^^^^ 12 | | 13 | = note: this error originates in the attribute macro `hidden_repr2` (in Nightly builds, run with -Z macro-backtrace for more info) 14 | 15 | error: #[pin_project] attribute may not be used on #[repr(packed)] types 16 | --> tests/ui/pin_project/packed_sneaky-1.rs:23:15 17 | | 18 | 23 | #[hidden_repr(packed)] 19 | | ^^^^^^ 20 | 21 | error: #[pin_project] attribute may not be used on #[repr(packed)] types 22 | --> tests/ui/pin_project/packed_sneaky-1.rs:32:15 23 | | 24 | 32 | #[hidden_repr(packed)] 25 | | ^^^^^^ 26 | -------------------------------------------------------------------------------- /tests/ui/pin_project/remove-attr-from-field.stderr: -------------------------------------------------------------------------------- 1 | error[E0308]: mismatched types 2 | --> tests/ui/pin_project/remove-attr-from-field.rs:30:38 3 | | 4 | 30 | let _: Pin<&mut PhantomPinned> = x.f; //~ ERROR E0308 5 | | ----------------------- ^^^ expected `Pin<&mut PhantomPinned>`, found `&mut PhantomPinned` 6 | | | 7 | | expected due to this 8 | | 9 | = note: expected struct `Pin<&mut PhantomPinned>` 10 | found mutable reference `&mut PhantomPinned` 11 | 12 | error[E0308]: mismatched types 13 | --> tests/ui/pin_project/remove-attr-from-field.rs:34:38 14 | | 15 | 34 | let _: Pin<&mut PhantomPinned> = x.f; //~ ERROR E0308 16 | | ----------------------- ^^^ expected `Pin<&mut PhantomPinned>`, found `&mut PhantomPinned` 17 | | | 18 | | expected due to this 19 | | 20 | = note: expected struct `Pin<&mut PhantomPinned>` 21 | found mutable reference `&mut PhantomPinned` 22 | -------------------------------------------------------------------------------- /tests/ui/pin_project/import_unnamed.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // Only named projected types can be imported. 4 | // See visibility.rs for named projected types. 5 | 6 | mod pub_ { 7 | use pin_project::pin_project; 8 | 9 | #[pin_project] 10 | pub struct Default(()); 11 | 12 | #[pin_project(project_replace)] 13 | pub struct Replace(()); 14 | } 15 | #[allow(unused_imports)] 16 | pub mod use_ { 17 | #[rustfmt::skip] 18 | use crate::pub_::__DefaultProjection; //~ ERROR E0432 19 | #[rustfmt::skip] 20 | use crate::pub_::__DefaultProjectionRef; //~ ERROR E0432 21 | #[rustfmt::skip] 22 | use crate::pub_::__ReplaceProjection; //~ ERROR E0432 23 | #[rustfmt::skip] 24 | use crate::pub_::__ReplaceProjectionOwned; //~ ERROR E0432 25 | #[rustfmt::skip] 26 | use crate::pub_::__ReplaceProjectionRef; //~ ERROR E0432 27 | 28 | // Confirm that the visibility of the original type is not changed. 29 | pub use crate::pub_::{Default, Replace}; 30 | } 31 | 32 | fn main() {} 33 | -------------------------------------------------------------------------------- /tests/ui/pin_project/packed_sneaky-1.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use std::pin::Pin; 4 | 5 | use auxiliary_macro::{hidden_repr, hidden_repr2}; 6 | use pin_project::{pin_project, pinned_drop, UnsafeUnpin}; 7 | 8 | #[pin_project] //~ ERROR may not be used on #[repr(packed)] types 9 | #[hidden_repr(packed)] 10 | struct A { 11 | #[pin] 12 | f: u32, 13 | } 14 | 15 | #[hidden_repr2] 16 | #[pin_project] //~ ERROR may not be used on #[repr(packed)] types 17 | struct B { 18 | #[pin] 19 | f: u32, 20 | } 21 | 22 | #[pin_project(UnsafeUnpin)] //~ ERROR may not be used on #[repr(packed)] types 23 | #[hidden_repr(packed)] 24 | struct C { 25 | #[pin] 26 | f: u32, 27 | } 28 | 29 | unsafe impl UnsafeUnpin for C {} 30 | 31 | #[pin_project(PinnedDrop)] //~ ERROR may not be used on #[repr(packed)] types 32 | #[hidden_repr(packed)] 33 | struct D { 34 | #[pin] 35 | f: u32, 36 | } 37 | 38 | #[pinned_drop] 39 | impl PinnedDrop for D { 40 | fn drop(self: Pin<&mut Self>) {} 41 | } 42 | 43 | fn main() {} 44 | -------------------------------------------------------------------------------- /tests/ui/pin_project/packed-name-value.stderr: -------------------------------------------------------------------------------- 1 | error: #[repr(packed)] attribute should not be name-value pair 2 | --> tests/ui/pin_project/packed-name-value.rs:18:8 3 | | 4 | 18 | #[repr(packed = "")] //~ ERROR attribute should not be name-value pair 5 | | ^^^^^^^^^^^ 6 | 7 | error: #[repr(packed)] attribute should not be name-value pair 8 | --> tests/ui/pin_project/packed-name-value.rs:23:8 9 | | 10 | 23 | #[repr(packed = "")] //~ ERROR attribute should not be name-value pair 11 | | ^^^^^^^^^^^ 12 | 13 | error[E0693]: incorrect `repr(packed)` attribute format 14 | --> tests/ui/pin_project/packed-name-value.rs:18:8 15 | | 16 | 18 | #[repr(packed = "")] //~ ERROR attribute should not be name-value pair 17 | | ^^^^^^^^^^^ help: use parentheses instead: `packed()` 18 | 19 | error[E0693]: incorrect `repr(packed)` attribute format 20 | --> tests/ui/pin_project/packed-name-value.rs:23:8 21 | | 22 | 23 | #[repr(packed = "")] //~ ERROR attribute should not be name-value pair 23 | | ^^^^^^^^^^^ help: use parentheses instead: `packed()` 24 | -------------------------------------------------------------------------------- /.deny.toml: -------------------------------------------------------------------------------- 1 | # https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html 2 | [advisories] 3 | yanked = "deny" 4 | git-fetch-with-cli = true 5 | ignore = [ 6 | ] 7 | 8 | # https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html 9 | [bans] 10 | multiple-versions = "warn" 11 | wildcards = "deny" 12 | allow-wildcard-paths = true 13 | build.executables = "deny" 14 | build.interpreted = "deny" 15 | build.include-dependencies = true 16 | build.include-workspace = false # covered by tools/tidy.sh 17 | build.include-archives = true 18 | build.allow-build-scripts = [ 19 | { name = "proc-macro2" }, 20 | { name = "quote" }, 21 | ] 22 | build.bypass = [ 23 | ] 24 | 25 | # https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html 26 | [licenses] 27 | unused-allowed-license = "deny" 28 | private.ignore = true 29 | allow = [ 30 | "Apache-2.0", 31 | "MIT", 32 | "Unicode-3.0", # unicode-ident 33 | ] 34 | 35 | # https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html 36 | [sources] 37 | unknown-registry = "deny" 38 | unknown-git = "deny" 39 | allow-git = [ 40 | ] 41 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /tests/ui/pin_project/override-priv-mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // https://discord.com/channels/273534239310479360/512792629516173323/870075511009857617 4 | 5 | #![allow(hidden_glob_reexports)] 6 | 7 | extern crate pin_project as pin_project_orig; 8 | extern crate self as pin_project; 9 | 10 | pub use ::pin_project_orig::*; 11 | mod __private { 12 | pub use ::pin_project_orig::__private::*; 13 | pub trait Drop {} 14 | } 15 | 16 | use std::{marker::PhantomPinned, mem}; 17 | 18 | #[pin_project] //~ ERROR conflicting implementations of trait `_::FooMustNotImplDrop` 19 | struct S { 20 | #[pin] 21 | f: (u8, PhantomPinned), 22 | } 23 | 24 | impl Drop for S { 25 | fn drop(&mut self) { 26 | let prev = &self.f.0 as *const _ as usize; 27 | let moved = mem::take(&mut self.f); // move pinned field 28 | let moved = &moved.0 as *const _ as usize; 29 | assert_eq!(prev, moved); // panic 30 | } 31 | } 32 | 33 | fn main() { 34 | let mut x = Box::pin(S { f: (1, PhantomPinned) }); 35 | let _f = x.as_mut().project().f; // first mutable access 36 | } 37 | -------------------------------------------------------------------------------- /pin-project-internal/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /tests/ui/not_unpin/conflict-unpin.stderr: -------------------------------------------------------------------------------- 1 | error[E0119]: conflicting implementations of trait `Unpin` for type `Foo<_, _>` 2 | --> tests/ui/not_unpin/conflict-unpin.rs:5:15 3 | | 4 | 5 | #[pin_project(!Unpin)] //~ ERROR E0119 5 | | ^^^^^^ conflicting implementation for `Foo<_, _>` 6 | ... 7 | 12 | impl Unpin for Foo where T: Unpin {} 8 | | --------------------------------------------- first implementation here 9 | 10 | error[E0119]: conflicting implementations of trait `Unpin` for type `Bar<_, _>` 11 | --> tests/ui/not_unpin/conflict-unpin.rs:14:15 12 | | 13 | 14 | #[pin_project(!Unpin)] //~ ERROR E0119 14 | | ^^^^^^ conflicting implementation for `Bar<_, _>` 15 | ... 16 | 21 | impl Unpin for Bar {} 17 | | ------------------------------ first implementation here 18 | 19 | error[E0119]: conflicting implementations of trait `Unpin` for type `Baz<_, _>` 20 | --> tests/ui/not_unpin/conflict-unpin.rs:23:15 21 | | 22 | 23 | #[pin_project(!Unpin)] //~ ERROR E0119 23 | | ^^^^^^ conflicting implementation for `Baz<_, _>` 24 | ... 25 | 30 | impl Unpin for Baz {} 26 | | -------------------------------------------- first implementation here 27 | -------------------------------------------------------------------------------- /tests/ui/unstable-features/trivial_bounds.stderr: -------------------------------------------------------------------------------- 1 | error: trait bound PhantomPinned: Unpin does not depend on any type or lifetime parameters 2 | --> tests/ui/unstable-features/trivial_bounds.rs:18:43 3 | | 4 | 18 | impl Unpin for A where PhantomPinned: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters 5 | | ^^^^^ 6 | | 7 | note: the lint level is defined here 8 | --> tests/ui/unstable-features/trivial_bounds.rs:8:9 9 | | 10 | 8 | #![deny(trivial_bounds)] 11 | | ^^^^^^^^^^^^^^ 12 | 13 | error: trait bound Inner: Unpin does not depend on any type or lifetime parameters 14 | --> tests/ui/unstable-features/trivial_bounds.rs:22:35 15 | | 16 | 22 | impl Unpin for B where Inner: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters 17 | | ^^^^^ 18 | 19 | error: trait bound Wrapper: Unpin does not depend on any type or lifetime parameters 20 | --> tests/ui/unstable-features/trivial_bounds.rs:30:44 21 | | 22 | 30 | impl Unpin for C where Wrapper: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters 23 | | ^^^^^ 24 | -------------------------------------------------------------------------------- /tests/ui/unsafe_unpin/conflict-unpin.stderr: -------------------------------------------------------------------------------- 1 | error[E0119]: conflicting implementations of trait `Unpin` for type `Foo<_, _>` 2 | --> tests/ui/unsafe_unpin/conflict-unpin.rs:5:15 3 | | 4 | 5 | #[pin_project(UnsafeUnpin)] //~ ERROR E0119 5 | | ^^^^^^^^^^^ conflicting implementation for `Foo<_, _>` 6 | ... 7 | 12 | impl Unpin for Foo where T: Unpin {} 8 | | --------------------------------------------- first implementation here 9 | 10 | error[E0119]: conflicting implementations of trait `Unpin` for type `Bar<_, _>` 11 | --> tests/ui/unsafe_unpin/conflict-unpin.rs:14:15 12 | | 13 | 14 | #[pin_project(UnsafeUnpin)] //~ ERROR E0119 14 | | ^^^^^^^^^^^ conflicting implementation for `Bar<_, _>` 15 | ... 16 | 21 | impl Unpin for Bar {} 17 | | ------------------------------ first implementation here 18 | 19 | error[E0119]: conflicting implementations of trait `Unpin` for type `Baz<_, _>` 20 | --> tests/ui/unsafe_unpin/conflict-unpin.rs:23:15 21 | | 22 | 23 | #[pin_project(UnsafeUnpin)] //~ ERROR E0119 23 | | ^^^^^^^^^^^ conflicting implementation for `Baz<_, _>` 24 | ... 25 | 30 | impl Unpin for Baz {} 26 | | -------------------------------------------- first implementation here 27 | -------------------------------------------------------------------------------- /tests/ui/pinned_drop/invalid-self.stderr: -------------------------------------------------------------------------------- 1 | error: expected identifier, found keyword `self` 2 | --> tests/ui/pinned_drop/invalid-self.rs:10:26 3 | | 4 | 10 | fn take_ref_self(ref self: Pin<&mut Self>) {} //~ ERROR expected identifier, found keyword `self` 5 | | ^^^^ expected identifier, found keyword 6 | 7 | error: expected identifier, found keyword `self` 8 | --> tests/ui/pinned_drop/invalid-self.rs:11:34 9 | | 10 | 11 | fn take_ref_mut_self(ref mut self: Pin<&mut Self>) {} //~ ERROR expected identifier, found keyword `self` 11 | | ^^^^ expected identifier, found keyword 12 | 13 | error: expected parameter name, found `@` 14 | --> tests/ui/pinned_drop/invalid-self.rs:13:25 15 | | 16 | 13 | fn self_subpat(self @ S {}: Self) {} //~ ERROR expected one of `)`, `,`, or `:`, found `@` 17 | | ^ expected parameter name 18 | 19 | error: expected one of `)`, `,`, or `:`, found `@` 20 | --> tests/ui/pinned_drop/invalid-self.rs:13:25 21 | | 22 | 13 | fn self_subpat(self @ S {}: Self) {} //~ ERROR expected one of `)`, `,`, or `:`, found `@` 23 | | -^ expected one of `)`, `,`, or `:` 24 | | | 25 | | help: missing `,` 26 | -------------------------------------------------------------------------------- /tests/ui/pin_project/remove-attr-from-struct.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use std::{marker::PhantomPinned, pin::Pin}; 4 | 5 | use auxiliary_macro::remove_attr; 6 | use pin_project::pin_project; 7 | 8 | fn is_unpin() {} 9 | 10 | #[pin_project] 11 | #[remove_attr(struct_all)] 12 | struct A { 13 | #[pin] //~ ERROR cannot find attribute `pin` in this scope 14 | f: PhantomPinned, 15 | } 16 | 17 | #[remove_attr(struct_all)] 18 | #[pin_project] 19 | struct B { 20 | #[pin] //~ ERROR cannot find attribute `pin` in this scope 21 | f: PhantomPinned, 22 | } 23 | 24 | #[pin_project] //~ ERROR has been removed 25 | #[remove_attr(struct_pin)] 26 | struct C { 27 | f: PhantomPinned, 28 | } 29 | 30 | #[remove_attr(struct_pin)] 31 | #[pin_project] // Ok 32 | struct D { 33 | f: PhantomPinned, 34 | } 35 | 36 | fn main() { 37 | is_unpin::(); //~ ERROR E0277 38 | is_unpin::(); //~ ERROR E0277 39 | is_unpin::(); // Ok 40 | 41 | let mut x = A { f: PhantomPinned }; 42 | let _ = Pin::new(&mut x).project(); //~ ERROR E0277,E0599 43 | 44 | let mut x = B { f: PhantomPinned }; 45 | let _ = Pin::new(&mut x).project(); //~ ERROR E0277,E0599 46 | 47 | let mut x = D { f: PhantomPinned }; 48 | let _ = Pin::new(&mut x).project(); //~ Ok 49 | } 50 | -------------------------------------------------------------------------------- /tests/no-core/lib.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | #![cfg(nightly)] 4 | #![no_core] 5 | #![feature(no_core)] 6 | 7 | // Make sure the items generated by pin-project don't depend on paths like 8 | // `core`, `core::prelude::*`, etc. 9 | // 10 | // Note: 11 | // - pin-project depends on core's items and is not really usable 12 | // in a no-core environment. 13 | // - If the procedural macro crate does not have its own items, it may be 14 | // preferable not to support this for compatibility with reexport. 15 | 16 | extern crate core as _core; 17 | 18 | // Dummy module to check that the expansion refers to the crate. 19 | mod pin_project {} 20 | 21 | // This works in 2018 edition, but in 2015 edition it gives an error: 22 | // ```text 23 | // error[E0659]: `pin` is ambiguous (derive helper attribute vs any other name) 24 | // --> tests/rust-2015/../include/basic-safe-part.rs:3:1 25 | // | 26 | // 3 | #[pin_project] 27 | // | ^^^^^^^^^^^^^^ ambiguous name 28 | // | 29 | // ``` 30 | #[allow(unused_imports)] 31 | use ::pin_project as pin; 32 | 33 | pub mod module { 34 | use _core::{fmt::Debug, include, prelude::v1::derive}; 35 | 36 | include!("../include/basic.rs"); 37 | } 38 | 39 | use _core::{fmt::Debug, include, prelude::v1::derive}; 40 | 41 | include!("../include/basic.rs"); 42 | -------------------------------------------------------------------------------- /tests/ui/pin_project/packed-enum.stderr: -------------------------------------------------------------------------------- 1 | error: #[repr(packed)] attribute should be applied to a struct or union 2 | --> tests/ui/pin_project/packed-enum.rs:15:8 3 | | 4 | 15 | #[repr(packed)] //~ ERROR E0517 5 | | ^^^^^^ 6 | 7 | error: #[repr(packed)] attribute should be applied to a struct or union 8 | --> tests/ui/pin_project/packed-enum.rs:20:8 9 | | 10 | 20 | #[repr(packed)] //~ ERROR E0517 11 | | ^^^^^^ 12 | 13 | error[E0517]: attribute should be applied to a struct or union 14 | --> tests/ui/pin_project/packed-enum.rs:9:8 15 | | 16 | 9 | #[repr(packed)] //~ ERROR E0517 17 | | ^^^^^^ 18 | 10 | / enum E1 { 19 | 11 | | V(()), 20 | 12 | | } 21 | | |_- not a struct or union 22 | 23 | error[E0517]: attribute should be applied to a struct or union 24 | --> tests/ui/pin_project/packed-enum.rs:15:8 25 | | 26 | 15 | #[repr(packed)] //~ ERROR E0517 27 | | ^^^^^^ 28 | 16 | / enum E2 { 29 | 17 | | V(()), 30 | 18 | | } 31 | | |_- not a struct or union 32 | 33 | error[E0517]: attribute should be applied to a struct or union 34 | --> tests/ui/pin_project/packed-enum.rs:20:8 35 | | 36 | 20 | #[repr(packed)] //~ ERROR E0517 37 | | ^^^^^^ 38 | 21 | #[pin_project] 39 | 22 | / enum E3 { 40 | 23 | | V(()), 41 | 24 | | } 42 | | |_- not a struct or union 43 | -------------------------------------------------------------------------------- /tests/ui/unstable-features/trivial_bounds.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // Note: If you change this test, change 'trivial_bounds-feature-gate.rs' at the same time. 4 | 5 | // trivial_bounds 6 | // Tracking issue: https://github.com/rust-lang/rust/issues/48214 7 | #![feature(trivial_bounds)] 8 | #![deny(trivial_bounds)] 9 | #![allow(dead_code)] 10 | 11 | use std::marker::{PhantomData, PhantomPinned}; 12 | 13 | fn inner() { 14 | struct Inner(PhantomPinned); 15 | 16 | struct A(PhantomPinned); 17 | 18 | impl Unpin for A where PhantomPinned: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters 19 | 20 | struct B(Inner); 21 | 22 | impl Unpin for B where Inner: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters 23 | 24 | struct Wrapper(T); 25 | 26 | impl Unpin for Wrapper where T: Unpin {} 27 | 28 | struct C(Inner); 29 | 30 | impl Unpin for C where Wrapper: Unpin {} //~ ERROR Unpin does not depend on any type or lifetime parameters 31 | 32 | struct WrapperWithLifetime<'a, T>(PhantomData<&'a ()>, T); 33 | 34 | impl Unpin for WrapperWithLifetime<'_, T> where T: Unpin {} 35 | 36 | struct D(Inner); 37 | 38 | impl<'a> Unpin for D where WrapperWithLifetime<'a, Inner>: Unpin {} // Ok 39 | } 40 | 41 | fn main() {} 42 | -------------------------------------------------------------------------------- /.shellcheckrc: -------------------------------------------------------------------------------- 1 | # ShellCheck configuration 2 | # https://github.com/koalaman/shellcheck/blob/HEAD/shellcheck.1.md#rc-files 3 | 4 | # See also: 5 | # https://github.com/koalaman/shellcheck/wiki/Optional 6 | # https://google.github.io/styleguide/shellguide.html 7 | 8 | # https://github.com/koalaman/shellcheck/wiki/Directive#external-sources 9 | external-sources=true 10 | 11 | # https://github.com/koalaman/shellcheck/wiki/SC2249 12 | # enable=add-default-case 13 | 14 | # https://github.com/koalaman/shellcheck/wiki/SC2244 15 | enable=avoid-nullary-conditions 16 | 17 | # https://github.com/koalaman/shellcheck/wiki/SC2312 18 | # enable=check-extra-masked-returns 19 | 20 | # https://github.com/koalaman/shellcheck/wiki/SC2310 21 | # https://github.com/koalaman/shellcheck/wiki/SC2311 22 | # enable=check-set-e-suppressed 23 | 24 | # enable=check-unassigned-uppercase 25 | 26 | # https://github.com/koalaman/shellcheck/wiki/SC2230 27 | enable=deprecate-which 28 | 29 | # https://github.com/koalaman/shellcheck/wiki/SC2248 30 | enable=quote-safe-variables 31 | 32 | # https://github.com/koalaman/shellcheck/wiki/SC2292 33 | # https://google.github.io/styleguide/shellguide.html#s6.3-tests 34 | enable=require-double-brackets 35 | 36 | # https://github.com/koalaman/shellcheck/wiki/SC2250 37 | # https://google.github.io/styleguide/shellguide.html#s5.6-variable-expansion 38 | enable=require-variable-braces 39 | -------------------------------------------------------------------------------- /tests/ui/pin_project/overlapping_unpin_struct.stderr: -------------------------------------------------------------------------------- 1 | error[E0277]: `PhantomPinned` cannot be unpinned 2 | --> tests/ui/pin_project/overlapping_unpin_struct.rs:20:16 3 | | 4 | 20 | is_unpin::>(); //~ ERROR E0277 5 | | ^^^^^^^^^^^^^^^^ within `_::__S<'_, PhantomPinned>`, the trait `Unpin` is not implemented for `PhantomPinned` 6 | | 7 | = note: consider using the `pin!` macro 8 | consider using `Box::pin` if you need to access the pinned value outside of the current scope 9 | note: required because it appears within the type `_::__S<'_, PhantomPinned>` 10 | --> tests/ui/pin_project/overlapping_unpin_struct.rs:8:8 11 | | 12 | 8 | struct S { 13 | | ^ 14 | note: required for `S` to implement `Unpin` 15 | --> tests/ui/pin_project/overlapping_unpin_struct.rs:7:1 16 | | 17 | 7 | #[pin_project] 18 | | ^^^^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro 19 | 8 | struct S { 20 | | ^^^^ 21 | note: required by a bound in `is_unpin` 22 | --> tests/ui/pin_project/overlapping_unpin_struct.rs:17:16 23 | | 24 | 17 | fn is_unpin() {} 25 | | ^^^^^ required by this bound in `is_unpin` 26 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 27 | -------------------------------------------------------------------------------- /tests/ui/pin_project/packed_sneaky-3.stderr: -------------------------------------------------------------------------------- 1 | error: expected item after attributes 2 | --> tests/ui/pin_project/packed_sneaky-3.rs:6:1 3 | | 4 | 6 | hidden_repr_macro! {} //~ ERROR expected item after attributes 5 | | ^^^^^^^^^^^^^^^^^^^^^ 6 | | 7 | = note: this error originates in the macro `hidden_repr_macro` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | 9 | error: expected item after attributes 10 | --> tests/ui/pin_project/packed_sneaky-3.rs:15:9 11 | | 12 | 15 | #[repr(packed)] //~ ERROR expected item after attributes 13 | | ^^^^^^^^^^^^^^^ 14 | ... 15 | 19 | hidden_repr_macro2! {} 16 | | ---------------------- in this macro invocation 17 | | 18 | = note: this error originates in the macro `hidden_repr_macro2` (in Nightly builds, run with -Z macro-backtrace for more info) 19 | 20 | error: expected item after attributes 21 | --> tests/ui/pin_project/packed_sneaky-3.rs:26:10 22 | | 23 | 26 | #[derive(HiddenRepr)] //~ ERROR expected item after attributes 24 | | ^^^^^^^^^^ 25 | | 26 | = note: this error originates in the derive macro `HiddenRepr` (in Nightly builds, run with -Z macro-backtrace for more info) 27 | 28 | error: proc-macro derive produced unparsable tokens 29 | --> tests/ui/pin_project/packed_sneaky-3.rs:26:10 30 | | 31 | 26 | #[derive(HiddenRepr)] //~ ERROR expected item after attributes 32 | | ^^^^^^^^^^ 33 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | # Rustfmt configuration 2 | # https://github.com/rust-lang/rustfmt/blob/HEAD/Configurations.md 3 | 4 | # Rustfmt cannot format long lines inside macros, but this option detects this. 5 | # This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3391) 6 | error_on_line_overflow = true 7 | 8 | # Override the default formatting style. 9 | # See https://internals.rust-lang.org/t/running-rustfmt-on-rust-lang-rust-and-other-rust-lang-repositories/8732/81. 10 | use_small_heuristics = "Max" 11 | # This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3370) 12 | overflow_delimited_expr = true 13 | # This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/4991). 14 | imports_granularity = "Crate" 15 | # This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/5083). 16 | group_imports = "StdExternalCrate" 17 | 18 | # Apply rustfmt to more places. 19 | # This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3348). 20 | format_code_in_doc_comments = true 21 | 22 | # Automatically fix deprecated style. 23 | use_field_init_shorthand = true 24 | use_try_shorthand = true 25 | 26 | # Set the default settings again to always apply the proper formatting without 27 | # being affected by the editor settings. 28 | edition = "2021" 29 | style_edition = "2024" 30 | hard_tabs = false 31 | newline_style = "Unix" 32 | tab_spaces = 4 33 | -------------------------------------------------------------------------------- /tests/ui/pin_project/unaligned_references.stderr: -------------------------------------------------------------------------------- 1 | error[E0793]: reference to field of packed struct is unaligned 2 | --> tests/ui/pin_project/unaligned_references.rs:17:13 3 | | 4 | 17 | let _ = &a.f; //~ ERROR reference to packed field is unaligned 5 | | ^^^^ 6 | | 7 | = note: this struct is 1-byte aligned, but the type of this field may require higher alignment 8 | = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) 9 | = 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) 10 | 11 | error[E0793]: reference to field of packed struct is unaligned 12 | --> tests/ui/pin_project/unaligned_references.rs:20:13 13 | | 14 | 20 | let _ = &b.f; //~ ERROR reference to packed field is unaligned 15 | | ^^^^ 16 | | 17 | = note: this struct is at most 2-byte aligned, but the type of this field may require higher alignment 18 | = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) 19 | = 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) 20 | -------------------------------------------------------------------------------- /tests/unsafe_unpin.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | #![allow(dead_code, clippy::undocumented_unsafe_blocks)] 4 | 5 | #[macro_use] 6 | mod auxiliary; 7 | 8 | use std::marker::PhantomPinned; 9 | 10 | use pin_project::{UnsafeUnpin, pin_project}; 11 | 12 | #[pin_project(UnsafeUnpin)] 13 | struct Blah { 14 | f1: U, 15 | #[pin] 16 | f2: T, 17 | } 18 | 19 | unsafe impl UnsafeUnpin for Blah {} 20 | 21 | assert_unpin!(Blah<(), ()>); 22 | assert_unpin!(Blah<(), PhantomPinned>); 23 | assert_not_unpin!(Blah); 24 | assert_not_unpin!(Blah); 25 | 26 | #[pin_project(UnsafeUnpin)] 27 | struct OverlappingLifetimeNames<'pin, T, U> { 28 | #[pin] 29 | f1: U, 30 | #[pin] 31 | f2: Option, 32 | f3: &'pin (), 33 | } 34 | 35 | unsafe impl UnsafeUnpin for OverlappingLifetimeNames<'_, T, U> {} 36 | 37 | assert_unpin!(OverlappingLifetimeNames<'_, (), ()>); 38 | assert_not_unpin!(OverlappingLifetimeNames<'_, PhantomPinned, ()>); 39 | assert_not_unpin!(OverlappingLifetimeNames<'_, (), PhantomPinned>); 40 | assert_not_unpin!(OverlappingLifetimeNames<'_, PhantomPinned, PhantomPinned>); 41 | 42 | #[test] 43 | fn trivial_bounds() { 44 | #[pin_project(UnsafeUnpin)] 45 | struct NotImplementUnsafeUnpin { 46 | #[pin] 47 | f: PhantomPinned, 48 | } 49 | 50 | assert_not_unpin!(NotImplementUnsafeUnpin); 51 | } 52 | -------------------------------------------------------------------------------- /DEVELOPMENT.md: -------------------------------------------------------------------------------- 1 | # Development Guide 2 | 3 | ## Testing 4 | 5 | To run all tests, run the following command: 6 | 7 | ```sh 8 | cargo +nightly test --all 9 | ``` 10 | 11 | ### UI tests (`tests/ui`, `tests/compiletest.rs`) 12 | 13 | This checks errors detected by the macro or the Rust compiler in the resulting 14 | expanded code. 15 | 16 | To run this test, run the following command: 17 | 18 | ```sh 19 | cargo +nightly test --test compiletest 20 | ``` 21 | 22 | Locally, this test updates the files in the `ui` directory if there are 23 | changes to the generated code. If there are any changes to the files in the 24 | `ui` directory after running the test, please commit them. 25 | 26 | See also [`trybuild` documentation](https://docs.rs/trybuild). 27 | 28 | ### Expansion tests (`tests/expand`, `tests/expandtest.rs`) 29 | 30 | Similar to ui tests, but instead of checking the compiler output, this checks 31 | the code generated by macros. 32 | 33 | See [examples](examples/README.md) for descriptions of what the generated 34 | code does, and why it needs to be generated. 35 | 36 | To run this test, run the following command: 37 | 38 | ```sh 39 | cargo +nightly test --test expandtest 40 | ``` 41 | 42 | Locally, this test updates the files in the `expand` directory if there are 43 | changes to the generated code. If there are any changes to the files in the 44 | `expand` directory after running the test, please commit them. 45 | 46 | See also [`macrotest` documentation](https://docs.rs/macrotest). 47 | -------------------------------------------------------------------------------- /tests/ui/pin_project/packed_sneaky-4.stderr: -------------------------------------------------------------------------------- 1 | error[E0793]: reference to field of packed struct is unaligned 2 | --> tests/ui/pin_project/packed_sneaky-4.rs:12:5 3 | | 4 | 12 | f: u32, 5 | | ^ 6 | | 7 | = note: this struct is 1-byte aligned, but the type of this field may require higher alignment 8 | = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) 9 | = 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) 10 | 11 | error[E0793]: reference to field of packed struct is unaligned 12 | --> tests/ui/pin_project/packed_sneaky-4.rs:8:1 13 | | 14 | 8 | #[pin_project] //~ ERROR reference to packed field is unaligned 15 | | ^^^^^^^^^^^^^^ 16 | | 17 | = note: this struct is 1-byte aligned, but the type of this field may require higher alignment 18 | = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) 19 | = 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) 20 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 21 | -------------------------------------------------------------------------------- /tests/ui/pin_project/import_unnamed.stderr: -------------------------------------------------------------------------------- 1 | error[E0432]: unresolved import `crate::pub_::__DefaultProjection` 2 | --> tests/ui/pin_project/import_unnamed.rs:18:9 3 | | 4 | 18 | use crate::pub_::__DefaultProjection; //~ ERROR E0432 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `__DefaultProjection` in `pub_` 6 | 7 | error[E0432]: unresolved import `crate::pub_::__DefaultProjectionRef` 8 | --> tests/ui/pin_project/import_unnamed.rs:20:9 9 | | 10 | 20 | use crate::pub_::__DefaultProjectionRef; //~ ERROR E0432 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `__DefaultProjectionRef` in `pub_` 12 | 13 | error[E0432]: unresolved import `crate::pub_::__ReplaceProjection` 14 | --> tests/ui/pin_project/import_unnamed.rs:22:9 15 | | 16 | 22 | use crate::pub_::__ReplaceProjection; //~ ERROR E0432 17 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `__ReplaceProjection` in `pub_` 18 | 19 | error[E0432]: unresolved import `crate::pub_::__ReplaceProjectionOwned` 20 | --> tests/ui/pin_project/import_unnamed.rs:24:9 21 | | 22 | 24 | use crate::pub_::__ReplaceProjectionOwned; //~ ERROR E0432 23 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `__ReplaceProjectionOwned` in `pub_` 24 | 25 | error[E0432]: unresolved import `crate::pub_::__ReplaceProjectionRef` 26 | --> tests/ui/pin_project/import_unnamed.rs:26:9 27 | | 28 | 26 | use crate::pub_::__ReplaceProjectionRef; //~ ERROR E0432 29 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `__ReplaceProjectionRef` in `pub_` 30 | -------------------------------------------------------------------------------- /tests/ui/pinned_drop/self.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | pub mod self_in_macro_def { 4 | use std::pin::Pin; 5 | 6 | use pin_project::{pin_project, pinned_drop}; 7 | 8 | #[pin_project(PinnedDrop)] 9 | pub struct S { 10 | f: (), 11 | } 12 | 13 | #[pinned_drop] 14 | impl PinnedDrop for S { 15 | fn drop(self: Pin<&mut Self>) { 16 | macro_rules! t { 17 | () => {{ 18 | let _ = self; //~ ERROR E0434 19 | 20 | fn f(self: ()) {} //~ ERROR `self` parameter is only allowed in associated functions 21 | }}; 22 | } 23 | t!(); 24 | } 25 | } 26 | } 27 | 28 | pub mod self_span { 29 | use std::pin::Pin; 30 | 31 | use pin_project::{pin_project, pinned_drop}; 32 | 33 | #[pin_project(PinnedDrop)] 34 | pub struct S { 35 | f: (), 36 | } 37 | 38 | #[pinned_drop] 39 | impl PinnedDrop for S { 40 | fn drop(self: Pin<&mut Self>) { 41 | let _: () = self; //~ ERROR E0308 42 | let _: Self = Self; //~ ERROR E0423 43 | } 44 | } 45 | 46 | #[pin_project(PinnedDrop)] 47 | pub enum E { 48 | V { f: () }, 49 | } 50 | 51 | #[pinned_drop] 52 | impl PinnedDrop for E { 53 | fn drop(self: Pin<&mut Self>) { 54 | let _: () = self; //~ ERROR E0308 55 | let _: Self = Self::V; //~ ERROR E0533 56 | } 57 | } 58 | } 59 | 60 | fn main() {} 61 | -------------------------------------------------------------------------------- /.cspell.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2", 3 | "gitignoreRoot": ".", 4 | "useGitignore": true, 5 | "dictionaryDefinitions": [ 6 | { 7 | "name": "organization-dictionary", 8 | "path": "https://raw.githubusercontent.com/taiki-e/github-actions/HEAD/.github/.cspell/organization-dictionary.txt", 9 | "addWords": true 10 | }, 11 | { 12 | "name": "project-dictionary", 13 | "path": "./.github/.cspell/project-dictionary.txt", 14 | "addWords": true 15 | }, 16 | { 17 | "name": "rust-dependencies", 18 | "path": "./.github/.cspell/rust-dependencies.txt", 19 | "addWords": true 20 | } 21 | ], 22 | "dictionaries": [ 23 | "organization-dictionary", 24 | "project-dictionary", 25 | "rust-dependencies" 26 | ], 27 | "ignoreRegExpList": [ 28 | // Copyright notice 29 | "Copyright .*", 30 | "SPDX-(File|Snippet)CopyrightText: .*", 31 | // GHA actions/workflows 32 | "uses: .+@[\\w_.-]+", 33 | // GHA context (repo name, owner name, etc.) 34 | "github.[\\w_.-]+ (=|!)= '[^']+'", 35 | // GH username 36 | "( |\\[)@[\\w_-]+", 37 | // Git config username 38 | "git config( --[^ ]+)? user.name .*", 39 | // Username in TODO|FIXME comment 40 | "(TODO|FIXME)\\([\\w_., -]+\\)", 41 | // Cargo.toml authors 42 | "authors *= *\\[[^\\]]*\\]", 43 | "\"[^\"]* <[\\w_.+-]+@[\\w.-]+>\"" 44 | ], 45 | "languageSettings": [ 46 | { 47 | "languageId": ["*"], 48 | "dictionaries": ["bash", "cpp-refined", "rust"] 49 | } 50 | ], 51 | "ignorePaths": [] 52 | } 53 | -------------------------------------------------------------------------------- /tests/ui/pinned_drop/conditional-drop-impl.stderr: -------------------------------------------------------------------------------- 1 | error[E0367]: `Drop` impl requires `T: Unpin` but the struct it is implemented for does not 2 | --> tests/ui/pinned_drop/conditional-drop-impl.rs:13:9 3 | | 4 | 13 | impl Drop for DropImpl { 5 | | ^^^^^ 6 | | 7 | note: the implementor must specify the same requirement 8 | --> tests/ui/pinned_drop/conditional-drop-impl.rs:9:1 9 | | 10 | 9 | struct DropImpl { 11 | | ^^^^^^^^^^^^^^^^^^ 12 | 13 | error[E0277]: `T` cannot be unpinned 14 | --> tests/ui/pinned_drop/conditional-drop-impl.rs:18:15 15 | | 16 | 18 | #[pin_project(PinnedDrop)] //~ ERROR E0277 17 | | ^^^^^^^^^^ the trait `Unpin` is not implemented for `T` 18 | | 19 | = note: consider using the `pin!` macro 20 | consider using `Box::pin` if you need to access the pinned value outside of the current scope 21 | note: required for `PinnedDropImpl` to implement `PinnedDrop` 22 | --> tests/ui/pinned_drop/conditional-drop-impl.rs:25:16 23 | | 24 | 24 | #[pinned_drop] 25 | | -------------- in this attribute macro expansion 26 | 25 | impl PinnedDrop for PinnedDropImpl { 27 | | ----- ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ 28 | | | 29 | | unsatisfied trait bound introduced here 30 | = note: this error originates in the attribute macro `pinned_drop` (in Nightly builds, run with -Z macro-backtrace for more info) 31 | help: consider restricting type parameter `T` with trait `Unpin` 32 | | 33 | 19 | struct PinnedDropImpl { 34 | | ++++++++++++++++++++ 35 | -------------------------------------------------------------------------------- /tests/ui/unstable-features/trivial_bounds-feature-gate.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // Note: If you change this test, change 'trivial_bounds.rs' at the same time. 4 | 5 | mod phantom_pinned { 6 | use std::marker::{PhantomData, PhantomPinned}; 7 | 8 | struct A(PhantomPinned); 9 | 10 | impl Unpin for A where PhantomPinned: Unpin {} //~ ERROR E0277 11 | 12 | struct Wrapper(T); 13 | 14 | impl Unpin for Wrapper where T: Unpin {} 15 | 16 | struct B(PhantomPinned); 17 | 18 | impl Unpin for B where Wrapper: Unpin {} //~ ERROR E0277 19 | 20 | struct WrapperWithLifetime<'a, T>(PhantomData<&'a ()>, T); 21 | 22 | impl Unpin for WrapperWithLifetime<'_, T> where T: Unpin {} 23 | 24 | struct C(PhantomPinned); 25 | 26 | impl<'a> Unpin for C where WrapperWithLifetime<'a, PhantomPinned>: Unpin {} // Ok 27 | } 28 | 29 | mod inner { 30 | use std::marker::{PhantomData, PhantomPinned}; 31 | 32 | struct Inner(PhantomPinned); 33 | 34 | struct A(Inner); 35 | 36 | impl Unpin for A where Inner: Unpin {} //~ ERROR E0277 37 | 38 | struct Wrapper(T); 39 | 40 | impl Unpin for Wrapper where T: Unpin {} 41 | 42 | struct B(Inner); 43 | 44 | impl Unpin for B where Wrapper: Unpin {} //~ ERROR E0277 45 | 46 | struct WrapperWithLifetime<'a, T>(PhantomData<&'a ()>, T); 47 | 48 | impl Unpin for WrapperWithLifetime<'_, T> where T: Unpin {} 49 | 50 | struct C(Inner); 51 | 52 | impl<'a> Unpin for C where WrapperWithLifetime<'a, Inner>: Unpin {} // Ok 53 | } 54 | 55 | fn main() {} 56 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples and generated code of each feature of pin-project 2 | 3 | ## Basic usage of `#[pin_project]` on structs 4 | 5 | - [example](struct-default.rs) 6 | - [generated code](struct-default-expanded.rs) 7 | 8 | ## Basic usage of `#[pin_project]` on enums 9 | 10 | - [example](enum-default.rs) 11 | - [generated code](enum-default-expanded.rs) 12 | 13 | ## Manual implementation of `Unpin` by `UnsafeUnpin` 14 | 15 | - [example](unsafe_unpin.rs) 16 | - [generated code](unsafe_unpin-expanded.rs) 17 | - [`UnsafeUnpin` documentation](https://docs.rs/pin-project/latest/pin_project/trait.UnsafeUnpin.html) 18 | 19 | ## Manual implementation of `Drop` by `#[pinned_drop]` 20 | 21 | - [example](pinned_drop.rs) 22 | - [generated code](pinned_drop-expanded.rs) 23 | - [`#[pinned_drop]` documentation](https://docs.rs/pin-project/latest/pin_project/attr.pinned_drop.html) 24 | 25 | ## `project_replace()` method 26 | 27 | - [example](project_replace.rs) 28 | - [generated code](project_replace-expanded.rs) 29 | - [`project_replace()` documentation](https://docs.rs/pin-project/latest/pin_project/attr.pin_project.html#project_replace-method) 30 | 31 | ## Ensure `!Unpin` by `#[pin_project(!Unpin)]` 32 | 33 | - [example](not_unpin.rs) 34 | - [generated code](not_unpin-expanded.rs) 35 | - [`!Unpin` documentation](https://docs.rs/pin-project/latest/pin_project/attr.pin_project.html#unpin) 36 | 37 | --- 38 | 39 | Note: These generated code examples are the little simplified version of the 40 | actual generated code. See [expansion tests](../tests#expansion-tests-expand-expandtestrs) if you 41 | want to see the exact version of the actual generated code. 42 | -------------------------------------------------------------------------------- /tests/ui/pin_project/visibility.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // Only named projected types can be imported. 4 | // See import_unnamed.rs for unnamed projected types. 5 | 6 | #![allow(unused_imports)] 7 | 8 | mod pub_ { 9 | use pin_project::pin_project; 10 | 11 | #[pin_project(project = DProj, project_ref = DProjRef)] 12 | pub struct Default(()); 13 | 14 | #[pin_project(project = RProj, project_ref = RProjRef, project_replace = RProjOwn)] 15 | pub struct Replace(()); 16 | } 17 | pub mod pub_use { 18 | #[rustfmt::skip] 19 | pub use crate::pub_::DProj; //~ ERROR E0365 20 | #[rustfmt::skip] 21 | pub use crate::pub_::DProjRef; //~ ERROR E0365 22 | #[rustfmt::skip] 23 | pub use crate::pub_::RProj; //~ ERROR E0365 24 | #[rustfmt::skip] 25 | pub use crate::pub_::RProjOwn; //~ ERROR E0365 26 | #[rustfmt::skip] 27 | pub use crate::pub_::RProjRef; //~ ERROR E0365 28 | 29 | // Confirm that the visibility of the original type is not changed. 30 | pub use crate::pub_::{Default, Replace}; 31 | } 32 | pub mod pub_use2 { 33 | // Ok 34 | pub(crate) use crate::pub_::{DProj, DProjRef, RProj, RProjOwn, RProjRef}; 35 | } 36 | 37 | mod pub_crate { 38 | use pin_project::pin_project; 39 | 40 | #[pin_project(project = DProj, project_ref = DProjRef)] 41 | pub(crate) struct Default(()); 42 | 43 | #[pin_project(project = RProj, project_ref = RProjRef, project_replace = RProjOwn)] 44 | pub(crate) struct Replace(()); 45 | } 46 | pub mod pub_crate_use { 47 | // Ok 48 | pub(crate) use crate::pub_crate::{DProj, DProjRef, RProj, RProjOwn, RProjRef}; 49 | } 50 | 51 | fn main() {} 52 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | permissions: 4 | contents: read 5 | 6 | on: 7 | pull_request: 8 | push: 9 | branches: 10 | - main 11 | - dev 12 | - v[0-9]+.[0-9]+ 13 | schedule: 14 | - cron: '0 2 * * *' 15 | workflow_dispatch: 16 | 17 | env: 18 | CARGO_INCREMENTAL: 0 19 | CARGO_NET_GIT_FETCH_WITH_CLI: true 20 | CARGO_NET_RETRY: 10 21 | CARGO_TERM_COLOR: always 22 | RUST_BACKTRACE: 1 23 | RUSTDOCFLAGS: -D warnings 24 | RUSTFLAGS: -D warnings 25 | RUSTUP_MAX_RETRIES: 10 26 | 27 | defaults: 28 | run: 29 | shell: bash --noprofile --norc -CeEuxo pipefail {0} 30 | 31 | concurrency: 32 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} 33 | cancel-in-progress: true 34 | 35 | jobs: 36 | miri: 37 | uses: taiki-e/github-actions/.github/workflows/miri.yml@main 38 | msrv: 39 | uses: taiki-e/github-actions/.github/workflows/msrv.yml@main 40 | test: 41 | uses: taiki-e/github-actions/.github/workflows/test.yml@main 42 | with: 43 | rust: 1.68,stable,beta,nightly 44 | tidy: 45 | uses: taiki-e/github-actions/.github/workflows/tidy.yml@main 46 | permissions: 47 | contents: read 48 | pull-requests: write # for gh pr edit --add-assignee 49 | repository-projects: read # for gh pr edit --add-assignee 50 | secrets: inherit 51 | 52 | no-std: 53 | runs-on: ubuntu-latest 54 | timeout-minutes: 60 55 | steps: 56 | - uses: taiki-e/checkout-action@v1 57 | - uses: taiki-e/github-actions/install-rust@nightly 58 | with: 59 | target: thumbv6m-none-eabi 60 | - run: cargo build --manifest-path tests/no-std/Cargo.toml --target thumbv6m-none-eabi 61 | - run: cargo build --manifest-path tests/rust-2015/Cargo.toml --target thumbv6m-none-eabi 62 | -------------------------------------------------------------------------------- /tests/ui/pin_project/conflict-unpin.stderr: -------------------------------------------------------------------------------- 1 | error[E0119]: conflicting implementations of trait `Unpin` for type `Foo<_, _>` 2 | --> tests/ui/pin_project/conflict-unpin.rs:7:1 3 | | 4 | 7 | #[pin_project] //~ ERROR E0119 5 | | ^^^^^^^^^^^^^^ conflicting implementation for `Foo<_, _>` 6 | ... 7 | 15 | impl Unpin for Foo where T: Unpin {} // Conditional Unpin impl 8 | | --------------------------------------------- first implementation here 9 | | 10 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 11 | 12 | error[E0119]: conflicting implementations of trait `Unpin` for type `Bar<_, _>` 13 | --> tests/ui/pin_project/conflict-unpin.rs:19:1 14 | | 15 | 19 | #[pin_project] //~ ERROR E0119 16 | | ^^^^^^^^^^^^^^ conflicting implementation for `Bar<_, _>` 17 | ... 18 | 27 | impl Unpin for Bar {} // Non-conditional Unpin impl 19 | | ------------------------------ first implementation here 20 | | 21 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 22 | 23 | error[E0119]: conflicting implementations of trait `Unpin` for type `Baz<_, _>` 24 | --> tests/ui/pin_project/conflict-unpin.rs:29:1 25 | | 26 | 29 | #[pin_project] //~ ERROR E0119 27 | | ^^^^^^^^^^^^^^ conflicting implementation for `Baz<_, _>` 28 | ... 29 | 37 | impl Unpin for Baz {} // Conditional Unpin impl 30 | | -------------------------------------------- first implementation here 31 | | 32 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 33 | -------------------------------------------------------------------------------- /tests/ui/pin_project/impl-unsafe-unpin.stderr: -------------------------------------------------------------------------------- 1 | error[E0119]: conflicting implementations of trait `UnsafeUnpin` for type `Foo<_, _>` 2 | --> tests/ui/pin_project/impl-unsafe-unpin.rs:5:1 3 | | 4 | 5 | #[pin_project] //~ ERROR E0119 5 | | ^^^^^^^^^^^^^^ conflicting implementation for `Foo<_, _>` 6 | ... 7 | 12 | unsafe impl UnsafeUnpin for Foo where T: Unpin {} 8 | | ---------------------------------------------------------- first implementation here 9 | | 10 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 11 | 12 | error[E0119]: conflicting implementations of trait `UnsafeUnpin` for type `Bar<_, _>` 13 | --> tests/ui/pin_project/impl-unsafe-unpin.rs:14:1 14 | | 15 | 14 | #[pin_project] //~ ERROR E0119 16 | | ^^^^^^^^^^^^^^ conflicting implementation for `Bar<_, _>` 17 | ... 18 | 21 | unsafe impl UnsafeUnpin for Bar {} 19 | | ------------------------------------------- first implementation here 20 | | 21 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 22 | 23 | error[E0119]: conflicting implementations of trait `UnsafeUnpin` for type `Baz<_, _>` 24 | --> tests/ui/pin_project/impl-unsafe-unpin.rs:23:1 25 | | 26 | 23 | #[pin_project] //~ ERROR E0119 27 | | ^^^^^^^^^^^^^^ conflicting implementation for `Baz<_, _>` 28 | ... 29 | 30 | unsafe impl UnsafeUnpin for Baz {} 30 | | --------------------------------------------------------- first implementation here 31 | | 32 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 33 | -------------------------------------------------------------------------------- /tests/ui/pin_project/visibility.stderr: -------------------------------------------------------------------------------- 1 | error[E0365]: `DProj` is only public within the crate, and cannot be re-exported outside 2 | --> tests/ui/pin_project/visibility.rs:19:13 3 | | 4 | 19 | pub use crate::pub_::DProj; //~ ERROR E0365 5 | | ^^^^^^^^^^^^^^^^^^ re-export of crate public `DProj` 6 | | 7 | = note: consider declaring type or module `DProj` with `pub` 8 | 9 | error[E0365]: `DProjRef` is only public within the crate, and cannot be re-exported outside 10 | --> tests/ui/pin_project/visibility.rs:21:13 11 | | 12 | 21 | pub use crate::pub_::DProjRef; //~ ERROR E0365 13 | | ^^^^^^^^^^^^^^^^^^^^^ re-export of crate public `DProjRef` 14 | | 15 | = note: consider declaring type or module `DProjRef` with `pub` 16 | 17 | error[E0365]: `RProj` is only public within the crate, and cannot be re-exported outside 18 | --> tests/ui/pin_project/visibility.rs:23:13 19 | | 20 | 23 | pub use crate::pub_::RProj; //~ ERROR E0365 21 | | ^^^^^^^^^^^^^^^^^^ re-export of crate public `RProj` 22 | | 23 | = note: consider declaring type or module `RProj` with `pub` 24 | 25 | error[E0365]: `RProjOwn` is only public within the crate, and cannot be re-exported outside 26 | --> tests/ui/pin_project/visibility.rs:25:13 27 | | 28 | 25 | pub use crate::pub_::RProjOwn; //~ ERROR E0365 29 | | ^^^^^^^^^^^^^^^^^^^^^ re-export of crate public `RProjOwn` 30 | | 31 | = note: consider declaring type or module `RProjOwn` with `pub` 32 | 33 | error[E0365]: `RProjRef` is only public within the crate, and cannot be re-exported outside 34 | --> tests/ui/pin_project/visibility.rs:27:13 35 | | 36 | 27 | pub use crate::pub_::RProjRef; //~ ERROR E0365 37 | | ^^^^^^^^^^^^^^^^^^^^^ re-export of crate public `RProjRef` 38 | | 39 | = note: consider declaring type or module `RProjRef` with `pub` 40 | -------------------------------------------------------------------------------- /tests/ui/pin_project/safe_packed_borrows.stderr: -------------------------------------------------------------------------------- 1 | error: lint `safe_packed_borrows` has been removed: converted into hard error, see issue #82523 for more information 2 | --> tests/ui/pin_project/safe_packed_borrows.rs:4:9 3 | | 4 | 4 | #![deny(safe_packed_borrows)] //~ ERROR has been renamed to `unaligned_references` 5 | | ^^^^^^^^^^^^^^^^^^^ 6 | | 7 | note: the lint level is defined here 8 | --> tests/ui/pin_project/safe_packed_borrows.rs:3:9 9 | | 10 | 3 | #![deny(renamed_and_removed_lints)] 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ 12 | 13 | error[E0793]: reference to field of packed struct is unaligned 14 | --> tests/ui/pin_project/safe_packed_borrows.rs:23:13 15 | | 16 | 23 | let _ = &a.f; 17 | | ^^^^ 18 | | 19 | = note: this struct is 1-byte aligned, but the type of this field may require higher alignment 20 | = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) 21 | = 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) 22 | 23 | error[E0793]: reference to field of packed struct is unaligned 24 | --> tests/ui/pin_project/safe_packed_borrows.rs:26:13 25 | | 26 | 26 | let _ = &b.f; 27 | | ^^^^ 28 | | 29 | = note: this struct is at most 2-byte aligned, but the type of this field may require higher alignment 30 | = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) 31 | = 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) 32 | -------------------------------------------------------------------------------- /tests/ui/not_unpin/impl-unsafe-unpin.stderr: -------------------------------------------------------------------------------- 1 | error[E0119]: conflicting implementations of trait `UnsafeUnpin` for type `Foo<_, _>` 2 | --> tests/ui/not_unpin/impl-unsafe-unpin.rs:5:1 3 | | 4 | 5 | #[pin_project(!Unpin)] //~ ERROR E0119 5 | | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Foo<_, _>` 6 | ... 7 | 12 | unsafe impl UnsafeUnpin for Foo where T: Unpin {} 8 | | ---------------------------------------------------------- first implementation here 9 | | 10 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 11 | 12 | error[E0119]: conflicting implementations of trait `UnsafeUnpin` for type `Bar<_, _>` 13 | --> tests/ui/not_unpin/impl-unsafe-unpin.rs:14:1 14 | | 15 | 14 | #[pin_project(!Unpin)] //~ ERROR E0119 16 | | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<_, _>` 17 | ... 18 | 21 | unsafe impl UnsafeUnpin for Bar {} 19 | | ------------------------------------------- first implementation here 20 | | 21 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 22 | 23 | error[E0119]: conflicting implementations of trait `UnsafeUnpin` for type `Baz<_, _>` 24 | --> tests/ui/not_unpin/impl-unsafe-unpin.rs:23:1 25 | | 26 | 23 | #[pin_project(!Unpin)] //~ ERROR E0119 27 | | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Baz<_, _>` 28 | ... 29 | 30 | unsafe impl UnsafeUnpin for Baz {} 30 | | --------------------------------------------------------- first implementation here 31 | | 32 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 33 | -------------------------------------------------------------------------------- /tests/repr_packed.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // unaligned_references did not exist in older compilers and safe_packed_borrows was removed in the latest compilers. 4 | // https://github.com/rust-lang/rust/pull/82525 5 | #![allow(unknown_lints, renamed_and_removed_lints)] 6 | #![forbid(unaligned_references, safe_packed_borrows)] 7 | 8 | use std::cell::Cell; 9 | 10 | // Ensure that the compiler doesn't copy the fields 11 | // of #[repr(packed)] types during drop, if the field has alignment 1 12 | // (that is, any reference to the field is guaranteed to have proper alignment) 13 | // We are currently unable to statically prevent the usage of #[pin_project] 14 | // on #[repr(packed)] types composed entirely of fields of alignment 1. 15 | // This shouldn't lead to undefined behavior, as long as the compiler doesn't 16 | // try to move the field anyway during drop. 17 | // 18 | // This tests validates that the compiler is doing what we expect. 19 | #[test] 20 | fn weird_repr_packed() { 21 | // We keep track of the field address during 22 | // drop using a thread local, to avoid changing 23 | // the layout of our #[repr(packed)] type. 24 | thread_local! { 25 | static FIELD_ADDR: Cell = const { Cell::new(0) }; 26 | } 27 | 28 | #[repr(packed)] 29 | struct Struct { 30 | field: u8, 31 | } 32 | 33 | impl Drop for Struct { 34 | fn drop(&mut self) { 35 | FIELD_ADDR.with(|f| { 36 | f.set(&self.field as *const u8 as usize); 37 | }); 38 | } 39 | } 40 | 41 | let field_addr = { 42 | // We let this field drop by going out of scope, 43 | // rather than explicitly calling drop(foo). 44 | // Calling drop(foo) causes 'foo' to be moved 45 | // into the 'drop' function, resulting in a different 46 | // address. 47 | let x = Struct { field: 27 }; 48 | &x.field as *const u8 as usize 49 | }; 50 | assert_eq!(field_addr, FIELD_ADDR.with(Cell::get)); 51 | } 52 | -------------------------------------------------------------------------------- /tests/expand/naming/enum-none.expanded.rs: -------------------------------------------------------------------------------- 1 | use pin_project::pin_project; 2 | #[pin(__private())] 3 | enum Enum { 4 | Struct { #[pin] pinned: T, unpinned: U }, 5 | Tuple(#[pin] T, U), 6 | Unit, 7 | } 8 | #[allow( 9 | unused_qualifications, 10 | deprecated, 11 | explicit_outlives_requirements, 12 | single_use_lifetimes, 13 | unreachable_pub, 14 | unused_tuple_struct_fields, 15 | clippy::unknown_clippy_lints, 16 | clippy::absolute_paths, 17 | clippy::min_ident_chars, 18 | clippy::pattern_type_mismatch, 19 | clippy::pub_with_shorthand, 20 | clippy::redundant_pub_crate, 21 | clippy::single_char_lifetime_names, 22 | clippy::type_repetition_in_bounds, 23 | clippy::elidable_lifetime_names, 24 | clippy::missing_const_for_fn, 25 | clippy::needless_lifetimes, 26 | clippy::semicolon_if_nothing_returned, 27 | clippy::use_self, 28 | clippy::used_underscore_binding 29 | )] 30 | const _: () = { 31 | #[allow(unused_extern_crates)] 32 | extern crate pin_project as _pin_project; 33 | impl Enum {} 34 | #[allow(missing_debug_implementations, unnameable_types)] 35 | struct __Enum<'pin, T, U> { 36 | __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< 37 | 'pin, 38 | ( 39 | _pin_project::__private::PhantomData, 40 | _pin_project::__private::PhantomData, 41 | ), 42 | >, 43 | __field0: T, 44 | __field1: T, 45 | } 46 | impl<'pin, T, U> _pin_project::__private::Unpin for Enum 47 | where 48 | _pin_project::__private::PinnedFieldsOf< 49 | __Enum<'pin, T, U>, 50 | >: _pin_project::__private::Unpin, 51 | {} 52 | #[doc(hidden)] 53 | unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum 54 | where 55 | _pin_project::__private::PinnedFieldsOf< 56 | __Enum<'pin, T, U>, 57 | >: _pin_project::__private::Unpin, 58 | {} 59 | trait EnumMustNotImplDrop {} 60 | #[allow(clippy::drop_bounds, drop_bounds)] 61 | impl EnumMustNotImplDrop for T {} 62 | impl EnumMustNotImplDrop for Enum {} 63 | #[doc(hidden)] 64 | impl _pin_project::__private::PinnedDrop for Enum { 65 | unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} 66 | } 67 | }; 68 | fn main() {} 69 | -------------------------------------------------------------------------------- /tests/ui/pin_project/add-pinned-field.stderr: -------------------------------------------------------------------------------- 1 | error[E0277]: `PhantomPinned` cannot be unpinned 2 | --> tests/ui/pin_project/add-pinned-field.rs:23:16 3 | | 4 | 23 | is_unpin::(); //~ ERROR E0277 5 | | ^^^ within `__Foo<'_>`, the trait `Unpin` is not implemented for `PhantomPinned` 6 | | 7 | = note: consider using the `pin!` macro 8 | consider using `Box::pin` if you need to access the pinned value outside of the current scope 9 | note: required because it appears within the type `__Foo<'_>` 10 | --> tests/ui/pin_project/add-pinned-field.rs:10:8 11 | | 12 | 10 | struct Foo { 13 | | ^^^ 14 | note: required for `Foo` to implement `Unpin` 15 | --> tests/ui/pin_project/add-pinned-field.rs:8:1 16 | | 17 | 8 | #[pin_project] 18 | | ^^^^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro 19 | 9 | #[add_pinned_field] 20 | 10 | struct Foo { 21 | | ^^^ 22 | note: required by a bound in `is_unpin` 23 | --> tests/ui/pin_project/add-pinned-field.rs:6:16 24 | | 25 | 6 | fn is_unpin() {} 26 | | ^^^^^ required by this bound in `is_unpin` 27 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 28 | 29 | error[E0277]: `PhantomPinned` cannot be unpinned 30 | --> tests/ui/pin_project/add-pinned-field.rs:24:16 31 | | 32 | 24 | is_unpin::(); //~ ERROR E0277 33 | | ^^^ within `__Bar<'_>`, the trait `Unpin` is not implemented for `PhantomPinned` 34 | | 35 | = note: consider using the `pin!` macro 36 | consider using `Box::pin` if you need to access the pinned value outside of the current scope 37 | note: required because it appears within the type `__Bar<'_>` 38 | --> tests/ui/pin_project/add-pinned-field.rs:17:8 39 | | 40 | 17 | struct Bar { 41 | | ^^^ 42 | note: required for `Bar` to implement `Unpin` 43 | --> tests/ui/pin_project/add-pinned-field.rs:16:1 44 | | 45 | 16 | #[pin_project] 46 | | ^^^^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro 47 | 17 | struct Bar { 48 | | ^^^ 49 | note: required by a bound in `is_unpin` 50 | --> tests/ui/pin_project/add-pinned-field.rs:6:16 51 | | 52 | 6 | fn is_unpin() {} 53 | | ^^^^^ required by this bound in `is_unpin` 54 | = note: this error originates in the derive macro `::pin_project::__private::__PinProjectInternalDerive` (in Nightly builds, run with -Z macro-backtrace for more info) 55 | -------------------------------------------------------------------------------- /tests/ui/pinned_drop/self.stderr: -------------------------------------------------------------------------------- 1 | error: `self` parameter is only allowed in associated functions 2 | --> tests/ui/pinned_drop/self.rs:20:26 3 | | 4 | 20 | fn f(self: ()) {} //~ ERROR `self` parameter is only allowed in associated functions 5 | | ^^^^ not semantically valid as function parameter 6 | ... 7 | 23 | t!(); 8 | | ---- in this macro invocation 9 | | 10 | = note: associated functions are those in `impl` or `trait` definitions 11 | = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) 12 | 13 | error[E0434]: can't capture dynamic environment in a fn item 14 | --> tests/ui/pinned_drop/self.rs:18:29 15 | | 16 | 18 | let _ = self; //~ ERROR E0434 17 | | ^^^^ 18 | ... 19 | 23 | t!(); 20 | | ---- in this macro invocation 21 | | 22 | = help: use the `|| { ... }` closure form instead 23 | = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) 24 | 25 | error[E0423]: expected value, found struct `S` 26 | --> tests/ui/pinned_drop/self.rs:42:27 27 | | 28 | 34 | / pub struct S { 29 | 35 | | f: (), 30 | 36 | | } 31 | | |_____- `S` defined here 32 | ... 33 | 42 | let _: Self = Self; //~ ERROR E0423 34 | | ^^^^ help: use struct literal syntax instead: `S { f: val }` 35 | 36 | error[E0308]: mismatched types 37 | --> tests/ui/pinned_drop/self.rs:41:25 38 | | 39 | 41 | let _: () = self; //~ ERROR E0308 40 | | -- ^^^^ expected `()`, found `Pin<&mut S>` 41 | | | 42 | | expected due to this 43 | | 44 | = note: expected unit type `()` 45 | found struct `Pin<&mut self_span::S>` 46 | 47 | error[E0308]: mismatched types 48 | --> tests/ui/pinned_drop/self.rs:54:25 49 | | 50 | 54 | let _: () = self; //~ ERROR E0308 51 | | -- ^^^^ expected `()`, found `Pin<&mut E>` 52 | | | 53 | | expected due to this 54 | | 55 | = note: expected unit type `()` 56 | found struct `Pin<&mut E>` 57 | 58 | error[E0533]: expected value, found struct variant `E::V` 59 | --> tests/ui/pinned_drop/self.rs:55:27 60 | | 61 | 55 | let _: Self = Self::V; //~ ERROR E0533 62 | | ^^^^^^^ not a value 63 | | 64 | help: you might have meant to create a new value of the struct 65 | | 66 | 55 | let _: Self = Self::V { f: /* value */ }; //~ ERROR E0533 67 | | ++++++++++++++++++ 68 | -------------------------------------------------------------------------------- /pin-project-internal/src/pin_project/attribute.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | use proc_macro2::TokenStream; 4 | use quote::quote; 5 | use syn::{ 6 | Attribute, Result, Token, Visibility, 7 | parse::{Parse, ParseStream}, 8 | }; 9 | 10 | use super::PIN; 11 | use crate::utils::SliceExt as _; 12 | 13 | // To generate the correct `Unpin` implementation and the projection methods, 14 | // we need to collect the types of the pinned fields. 15 | // However, since proc-macro-attribute is applied before `cfg` and `cfg_attr` 16 | // on fields, we cannot be collecting field types properly at this timing. 17 | // So instead of generating the `Unpin` implementation and the projection 18 | // methods here, delegate their processing to proc-macro-derive. 19 | // 20 | // At this stage, only attributes are parsed and the following attributes are 21 | // added to the attributes of the item. 22 | // - `#[derive(InternalDerive)]` - An internal helper macro that does the above 23 | // processing. 24 | // - `#[pin(__private(#args))]` - Pass the argument of `#[pin_project]` to 25 | // proc-macro-derive (`InternalDerive`). 26 | 27 | pub(super) fn parse_attribute(args: &TokenStream, input: TokenStream) -> Result { 28 | let Input { attrs, body } = syn::parse2(input)?; 29 | 30 | Ok(quote! { 31 | #(#attrs)* 32 | #[derive(::pin_project::__private::__PinProjectInternalDerive)] 33 | // Use `__private` to prevent users from trying to control `InternalDerive` 34 | // manually. `__private` does not guarantee compatibility between patch 35 | // versions, so it should be sufficient for this purpose in most cases. 36 | #[pin(__private(#args))] 37 | #body 38 | }) 39 | } 40 | 41 | struct Input { 42 | attrs: Vec, 43 | body: TokenStream, 44 | } 45 | 46 | impl Parse for Input { 47 | fn parse(input: ParseStream<'_>) -> Result { 48 | let attrs = input.call(Attribute::parse_outer)?; 49 | 50 | let ahead = input.fork(); 51 | let _vis: Visibility = ahead.parse()?; 52 | if !ahead.peek(Token![struct]) && !ahead.peek(Token![enum]) { 53 | // If we check this only on proc-macro-derive, it may generate unhelpful error 54 | // messages. So it is preferable to be able to detect it here. 55 | bail!( 56 | input.parse::()?, 57 | "#[pin_project] attribute may only be used on structs or enums" 58 | ); 59 | } else if let Some(attr) = attrs.find(PIN) { 60 | bail!(attr, "#[pin] attribute may only be used on fields of structs or variants"); 61 | } else if let Some(attr) = attrs.find("pin_project") { 62 | bail!(attr, "duplicate #[pin_project] attribute"); 63 | } 64 | Ok(Self { attrs, body: input.parse()? }) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tests/auxiliary/macro/lib.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | #![allow(clippy::missing_panics_doc)] 4 | 5 | use proc_macro::TokenStream; 6 | use quote::{ToTokens as _, format_ident, quote}; 7 | use syn::{Field, FieldMutability, Fields, ItemStruct, Token, Visibility, parse_quote}; 8 | 9 | fn tokens2(tokens: TokenStream) -> proc_macro2::TokenStream { 10 | tokens.into() 11 | } 12 | 13 | #[proc_macro_attribute] 14 | pub fn hidden_repr(args: TokenStream, input: TokenStream) -> TokenStream { 15 | let args = tokens2(args); 16 | let mut item = syn::parse_macro_input!(input as ItemStruct); 17 | item.attrs.push(parse_quote!(#[repr(#args)])); 18 | quote!(#item).into() 19 | } 20 | 21 | #[proc_macro_attribute] 22 | pub fn hidden_repr2(_args: TokenStream, input: TokenStream) -> TokenStream { 23 | let mut item = syn::parse_macro_input!(input as ItemStruct); 24 | item.attrs.push(parse_quote!(#[auxiliary_macro::hidden_repr(packed)] )); 25 | quote!(#item).into() 26 | } 27 | 28 | #[proc_macro] 29 | pub fn hidden_repr_macro(input: TokenStream) -> TokenStream { 30 | let input = tokens2(input); 31 | quote!(#[repr(packed)] #input).into() 32 | } 33 | 34 | #[proc_macro_derive(HiddenRepr)] 35 | pub fn hidden_repr_derive(_input: TokenStream) -> TokenStream { 36 | quote!(#[repr(packed)]).into() 37 | } 38 | 39 | #[proc_macro_attribute] 40 | pub fn hidden_repr_cfg_not_any(args: TokenStream, input: TokenStream) -> TokenStream { 41 | let (args, input) = (tokens2(args), tokens2(input)); 42 | quote!(#[cfg_attr(not(any()), repr(#args))] #input).into() 43 | } 44 | 45 | #[proc_macro_attribute] 46 | pub fn add_pinned_field(_: TokenStream, input: TokenStream) -> TokenStream { 47 | let mut item: ItemStruct = syn::parse_macro_input!(input); 48 | let Fields::Named(fields) = &mut item.fields else { unreachable!() }; 49 | fields.named.push(Field { 50 | attrs: vec![parse_quote!(#[pin])], 51 | vis: Visibility::Inherited, 52 | ident: Some(format_ident!("__field")), 53 | colon_token: Some(::default()), 54 | ty: parse_quote!(::std::marker::PhantomPinned), 55 | mutability: FieldMutability::None, 56 | }); 57 | 58 | item.into_token_stream().into() 59 | } 60 | 61 | #[proc_macro_attribute] 62 | pub fn remove_attr(args: TokenStream, input: TokenStream) -> TokenStream { 63 | let mut item: ItemStruct = syn::parse_macro_input!(input); 64 | match &*args.to_string() { 65 | "field_all" => { 66 | let Fields::Named(fields) = &mut item.fields else { unreachable!() }; 67 | fields.named.iter_mut().for_each(|field| field.attrs.clear()); 68 | } 69 | "struct_all" => item.attrs.clear(), 70 | "struct_pin" => { 71 | while item 72 | .attrs 73 | .iter() 74 | .position(|a| a.path().is_ident("pin")) 75 | .map(|i| item.attrs.remove(i)) 76 | .is_some() 77 | {} 78 | } 79 | _ => unreachable!(), 80 | } 81 | 82 | item.into_token_stream().into() 83 | } 84 | 85 | #[proc_macro_attribute] 86 | pub fn add_pin_attr(args: TokenStream, input: TokenStream) -> TokenStream { 87 | let mut item: ItemStruct = syn::parse_macro_input!(input); 88 | assert_eq!(&*args.to_string(), "struct"); 89 | item.attrs.push(parse_quote!(#[pin])); 90 | item.into_token_stream().into() 91 | } 92 | -------------------------------------------------------------------------------- /tests/expand/unsafe_unpin/tuple_struct.expanded.rs: -------------------------------------------------------------------------------- 1 | use pin_project::{pin_project, UnsafeUnpin}; 2 | #[pin(__private(UnsafeUnpin))] 3 | struct TupleStruct(#[pin] T, U); 4 | #[allow( 5 | unused_qualifications, 6 | deprecated, 7 | explicit_outlives_requirements, 8 | single_use_lifetimes, 9 | unreachable_pub, 10 | unused_tuple_struct_fields, 11 | clippy::unknown_clippy_lints, 12 | clippy::absolute_paths, 13 | clippy::min_ident_chars, 14 | clippy::pattern_type_mismatch, 15 | clippy::pub_with_shorthand, 16 | clippy::redundant_pub_crate, 17 | clippy::single_char_lifetime_names, 18 | clippy::type_repetition_in_bounds, 19 | clippy::elidable_lifetime_names, 20 | clippy::missing_const_for_fn, 21 | clippy::needless_lifetimes, 22 | clippy::semicolon_if_nothing_returned, 23 | clippy::use_self, 24 | clippy::used_underscore_binding 25 | )] 26 | const _: () = { 27 | #[allow(unused_extern_crates)] 28 | extern crate pin_project as _pin_project; 29 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::mut_mut)] 30 | struct __TupleStructProjection<'pin, T, U>( 31 | ::pin_project::__private::Pin<&'pin mut (T)>, 32 | &'pin mut (U), 33 | ) 34 | where 35 | TupleStruct: 'pin; 36 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::ref_option_ref)] 37 | struct __TupleStructProjectionRef<'pin, T, U>( 38 | ::pin_project::__private::Pin<&'pin (T)>, 39 | &'pin (U), 40 | ) 41 | where 42 | TupleStruct: 'pin; 43 | impl TupleStruct { 44 | #[allow(dead_code)] 45 | #[inline] 46 | fn project<'pin>( 47 | self: _pin_project::__private::Pin<&'pin mut Self>, 48 | ) -> __TupleStructProjection<'pin, T, U> { 49 | unsafe { 50 | let Self(_0, _1) = self.get_unchecked_mut(); 51 | __TupleStructProjection( 52 | _pin_project::__private::Pin::new_unchecked(_0), 53 | _1, 54 | ) 55 | } 56 | } 57 | #[allow(dead_code)] 58 | #[inline] 59 | fn project_ref<'pin>( 60 | self: _pin_project::__private::Pin<&'pin Self>, 61 | ) -> __TupleStructProjectionRef<'pin, T, U> { 62 | unsafe { 63 | let Self(_0, _1) = self.get_ref(); 64 | __TupleStructProjectionRef( 65 | _pin_project::__private::Pin::new_unchecked(_0), 66 | _1, 67 | ) 68 | } 69 | } 70 | } 71 | #[forbid(unaligned_references, safe_packed_borrows)] 72 | fn __assert_not_repr_packed(this: &TupleStruct) { 73 | let _ = &this.0; 74 | let _ = &this.1; 75 | } 76 | impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct 77 | where 78 | _pin_project::__private::PinnedFieldsOf< 79 | _pin_project::__private::Wrapper<'pin, Self>, 80 | >: _pin_project::UnsafeUnpin, 81 | {} 82 | trait TupleStructMustNotImplDrop {} 83 | #[allow(clippy::drop_bounds, drop_bounds)] 84 | impl TupleStructMustNotImplDrop for T {} 85 | impl TupleStructMustNotImplDrop for TupleStruct {} 86 | #[doc(hidden)] 87 | impl _pin_project::__private::PinnedDrop for TupleStruct { 88 | unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} 89 | } 90 | }; 91 | unsafe impl UnsafeUnpin for TupleStruct {} 92 | fn main() {} 93 | -------------------------------------------------------------------------------- /tests/expand/unsafe_unpin/struct.expanded.rs: -------------------------------------------------------------------------------- 1 | use pin_project::{pin_project, UnsafeUnpin}; 2 | #[pin(__private(UnsafeUnpin))] 3 | struct Struct { 4 | #[pin] 5 | pinned: T, 6 | unpinned: U, 7 | } 8 | #[allow( 9 | unused_qualifications, 10 | deprecated, 11 | explicit_outlives_requirements, 12 | single_use_lifetimes, 13 | unreachable_pub, 14 | unused_tuple_struct_fields, 15 | clippy::unknown_clippy_lints, 16 | clippy::absolute_paths, 17 | clippy::min_ident_chars, 18 | clippy::pattern_type_mismatch, 19 | clippy::pub_with_shorthand, 20 | clippy::redundant_pub_crate, 21 | clippy::single_char_lifetime_names, 22 | clippy::type_repetition_in_bounds, 23 | clippy::elidable_lifetime_names, 24 | clippy::missing_const_for_fn, 25 | clippy::needless_lifetimes, 26 | clippy::semicolon_if_nothing_returned, 27 | clippy::use_self, 28 | clippy::used_underscore_binding 29 | )] 30 | const _: () = { 31 | #[allow(unused_extern_crates)] 32 | extern crate pin_project as _pin_project; 33 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::mut_mut)] 34 | struct __StructProjection<'pin, T, U> 35 | where 36 | Struct: 'pin, 37 | { 38 | pinned: ::pin_project::__private::Pin<&'pin mut (T)>, 39 | unpinned: &'pin mut (U), 40 | } 41 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::ref_option_ref)] 42 | struct __StructProjectionRef<'pin, T, U> 43 | where 44 | Struct: 'pin, 45 | { 46 | pinned: ::pin_project::__private::Pin<&'pin (T)>, 47 | unpinned: &'pin (U), 48 | } 49 | impl Struct { 50 | #[allow(dead_code)] 51 | #[inline] 52 | fn project<'pin>( 53 | self: _pin_project::__private::Pin<&'pin mut Self>, 54 | ) -> __StructProjection<'pin, T, U> { 55 | unsafe { 56 | let Self { pinned, unpinned } = self.get_unchecked_mut(); 57 | __StructProjection { 58 | pinned: _pin_project::__private::Pin::new_unchecked(pinned), 59 | unpinned, 60 | } 61 | } 62 | } 63 | #[allow(dead_code)] 64 | #[inline] 65 | fn project_ref<'pin>( 66 | self: _pin_project::__private::Pin<&'pin Self>, 67 | ) -> __StructProjectionRef<'pin, T, U> { 68 | unsafe { 69 | let Self { pinned, unpinned } = self.get_ref(); 70 | __StructProjectionRef { 71 | pinned: _pin_project::__private::Pin::new_unchecked(pinned), 72 | unpinned, 73 | } 74 | } 75 | } 76 | } 77 | #[forbid(unaligned_references, safe_packed_borrows)] 78 | fn __assert_not_repr_packed(this: &Struct) { 79 | let _ = &this.pinned; 80 | let _ = &this.unpinned; 81 | } 82 | impl<'pin, T, U> _pin_project::__private::Unpin for Struct 83 | where 84 | _pin_project::__private::PinnedFieldsOf< 85 | _pin_project::__private::Wrapper<'pin, Self>, 86 | >: _pin_project::UnsafeUnpin, 87 | {} 88 | trait StructMustNotImplDrop {} 89 | #[allow(clippy::drop_bounds, drop_bounds)] 90 | impl StructMustNotImplDrop for T {} 91 | impl StructMustNotImplDrop for Struct {} 92 | #[doc(hidden)] 93 | impl _pin_project::__private::PinnedDrop for Struct { 94 | unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} 95 | } 96 | }; 97 | unsafe impl UnsafeUnpin for Struct {} 98 | fn main() {} 99 | -------------------------------------------------------------------------------- /tests/ui/unstable-features/trivial_bounds-feature-gate.stderr: -------------------------------------------------------------------------------- 1 | error[E0277]: `PhantomPinned` cannot be unpinned 2 | --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:10:28 3 | | 4 | 10 | impl Unpin for A where PhantomPinned: Unpin {} //~ ERROR E0277 5 | | ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `PhantomPinned` 6 | | 7 | = note: consider using the `pin!` macro 8 | consider using `Box::pin` if you need to access the pinned value outside of the current scope 9 | = help: see issue #48214 10 | help: add `#![feature(trivial_bounds)]` to the crate attributes to enable 11 | | 12 | 5 + #![feature(trivial_bounds)] 13 | | 14 | 15 | error[E0277]: `PhantomPinned` cannot be unpinned 16 | --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:18:28 17 | | 18 | 18 | impl Unpin for B where Wrapper: Unpin {} //~ ERROR E0277 19 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `PhantomPinned` 20 | | 21 | = note: consider using the `pin!` macro 22 | consider using `Box::pin` if you need to access the pinned value outside of the current scope 23 | note: required for `phantom_pinned::Wrapper` to implement `Unpin` 24 | --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:14:13 25 | | 26 | 14 | impl Unpin for Wrapper where T: Unpin {} 27 | | ^^^^^ ^^^^^^^^^^ ----- unsatisfied trait bound introduced here 28 | = help: see issue #48214 29 | help: add `#![feature(trivial_bounds)]` to the crate attributes to enable 30 | | 31 | 5 + #![feature(trivial_bounds)] 32 | | 33 | 34 | error[E0277]: `PhantomPinned` cannot be unpinned 35 | --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:36:28 36 | | 37 | 36 | impl Unpin for A where Inner: Unpin {} //~ ERROR E0277 38 | | ^^^^^^^^^^^^ within `Inner`, the trait `Unpin` is not implemented for `PhantomPinned` 39 | | 40 | = note: consider using the `pin!` macro 41 | consider using `Box::pin` if you need to access the pinned value outside of the current scope 42 | note: required because it appears within the type `Inner` 43 | --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:32:12 44 | | 45 | 32 | struct Inner(PhantomPinned); 46 | | ^^^^^ 47 | = help: see issue #48214 48 | help: add `#![feature(trivial_bounds)]` to the crate attributes to enable 49 | | 50 | 5 + #![feature(trivial_bounds)] 51 | | 52 | 53 | error[E0277]: `PhantomPinned` cannot be unpinned 54 | --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:44:28 55 | | 56 | 44 | impl Unpin for B where Wrapper: Unpin {} //~ ERROR E0277 57 | | ^^^^^^^^^^^^^^^^^^^^^ within `Inner`, the trait `Unpin` is not implemented for `PhantomPinned` 58 | | 59 | = note: consider using the `pin!` macro 60 | consider using `Box::pin` if you need to access the pinned value outside of the current scope 61 | note: required because it appears within the type `Inner` 62 | --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:32:12 63 | | 64 | 32 | struct Inner(PhantomPinned); 65 | | ^^^^^ 66 | note: required for `inner::Wrapper` to implement `Unpin` 67 | --> tests/ui/unstable-features/trivial_bounds-feature-gate.rs:40:13 68 | | 69 | 40 | impl Unpin for Wrapper where T: Unpin {} 70 | | ^^^^^ ^^^^^^^^^^ ----- unsatisfied trait bound introduced here 71 | = help: see issue #48214 72 | help: add `#![feature(trivial_bounds)]` to the crate attributes to enable 73 | | 74 | 5 + #![feature(trivial_bounds)] 75 | | 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pin-project 2 | 3 | [![crates.io](https://img.shields.io/crates/v/pin-project?style=flat-square&logo=rust)](https://crates.io/crates/pin-project) 4 | [![docs.rs](https://img.shields.io/badge/docs.rs-pin--project-blue?style=flat-square&logo=docs.rs)](https://docs.rs/pin-project) 5 | [![license](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue?style=flat-square)](#license) 6 | [![msrv](https://img.shields.io/badge/msrv-1.68-blue?style=flat-square&logo=rust)](https://www.rust-lang.org) 7 | [![github actions](https://img.shields.io/github/actions/workflow/status/taiki-e/pin-project/ci.yml?branch=main&style=flat-square&logo=github)](https://github.com/taiki-e/pin-project/actions) 8 | 9 | 10 | 11 | A crate for safe and ergonomic [pin-projection]. 12 | 13 | ## Usage 14 | 15 | Add this to your `Cargo.toml`: 16 | 17 | ```toml 18 | [dependencies] 19 | pin-project = "1" 20 | ``` 21 | 22 | ## Examples 23 | 24 | [`#[pin_project]`][`pin_project`] attribute creates projection types 25 | covering all the fields of struct or enum. 26 | 27 | ```rust 28 | use std::pin::Pin; 29 | 30 | use pin_project::pin_project; 31 | 32 | #[pin_project] 33 | struct Struct { 34 | #[pin] 35 | pinned: T, 36 | unpinned: U, 37 | } 38 | 39 | impl Struct { 40 | fn method(self: Pin<&mut Self>) { 41 | let this = self.project(); 42 | let _: Pin<&mut T> = this.pinned; // Pinned reference to the field 43 | let _: &mut U = this.unpinned; // Normal reference to the field 44 | } 45 | } 46 | ``` 47 | 48 | [*code like this will be generated*][struct-default-expanded] 49 | 50 | To use `#[pin_project]` on enums, you need to name the projection type 51 | returned from the method. 52 | 53 | ```rust 54 | use std::pin::Pin; 55 | 56 | use pin_project::pin_project; 57 | 58 | #[pin_project(project = EnumProj)] 59 | enum Enum { 60 | Pinned(#[pin] T), 61 | Unpinned(U), 62 | } 63 | 64 | impl Enum { 65 | fn method(self: Pin<&mut Self>) { 66 | match self.project() { 67 | EnumProj::Pinned(x) => { 68 | let _: Pin<&mut T> = x; 69 | } 70 | EnumProj::Unpinned(y) => { 71 | let _: &mut U = y; 72 | } 73 | } 74 | } 75 | } 76 | ``` 77 | 78 | [*code like this will be generated*][enum-default-expanded] 79 | 80 | See [`#[pin_project]`][`pin_project`] attribute for more details, and 81 | see [examples] directory for more examples and generated code. 82 | 83 | ## Related Projects 84 | 85 | - [pin-project-lite]: A lightweight version of pin-project written with declarative macros. 86 | 87 | [enum-default-expanded]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/enum-default-expanded.rs 88 | [examples]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/README.md 89 | [pin-project-lite]: https://github.com/taiki-e/pin-project-lite 90 | [pin-projection]: https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning 91 | [struct-default-expanded]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/struct-default-expanded.rs 92 | 93 | 94 | 95 | [`pin_project`]: https://docs.rs/pin-project/latest/pin_project/attr.pin_project.html 96 | 97 | ## License 98 | 99 | Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or 100 | [MIT license](LICENSE-MIT) at your option. 101 | 102 | Unless you explicitly state otherwise, any contribution intentionally submitted 103 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall 104 | be dual licensed as above, without any additional terms or conditions. 105 | -------------------------------------------------------------------------------- /tests/proper_unpin.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | #![allow(dead_code)] 4 | 5 | #[macro_use] 6 | mod auxiliary; 7 | 8 | pub mod default { 9 | use std::marker::PhantomPinned; 10 | 11 | use pin_project::pin_project; 12 | 13 | struct Inner { 14 | f: T, 15 | } 16 | 17 | assert_unpin!(Inner<()>); 18 | assert_not_unpin!(Inner); 19 | 20 | #[pin_project] 21 | struct Struct { 22 | #[pin] 23 | f1: Inner, 24 | f2: U, 25 | } 26 | 27 | assert_unpin!(Struct<(), ()>); 28 | assert_unpin!(Struct<(), PhantomPinned>); 29 | assert_not_unpin!(Struct); 30 | assert_not_unpin!(Struct); 31 | 32 | #[pin_project(project = EnumProj, project_ref = EnumProjRef)] 33 | enum Enum { 34 | V1 { 35 | #[pin] 36 | f1: Inner, 37 | f2: U, 38 | }, 39 | } 40 | 41 | assert_unpin!(Enum<(), ()>); 42 | assert_unpin!(Enum<(), PhantomPinned>); 43 | assert_not_unpin!(Enum); 44 | assert_not_unpin!(Enum); 45 | 46 | #[pin_project] 47 | struct TrivialBounds { 48 | #[pin] 49 | f: PhantomPinned, 50 | } 51 | 52 | assert_not_unpin!(TrivialBounds); 53 | 54 | #[pin_project] 55 | struct PinRef<'a, T, U> { 56 | #[pin] 57 | f1: &'a mut Inner, 58 | f2: U, 59 | } 60 | 61 | assert_unpin!(PinRef<'_, PhantomPinned, PhantomPinned>); 62 | } 63 | 64 | pub mod cfg { 65 | use std::marker::PhantomPinned; 66 | 67 | use pin_project::pin_project; 68 | 69 | #[pin_project] 70 | struct Foo { 71 | #[cfg(any())] 72 | #[pin] 73 | f: T, 74 | #[cfg(not(any()))] 75 | f: T, 76 | } 77 | 78 | assert_unpin!(Foo); 79 | 80 | #[pin_project] 81 | struct Bar { 82 | #[cfg(any())] 83 | f: T, 84 | #[cfg(not(any()))] 85 | #[pin] 86 | f: T, 87 | } 88 | 89 | assert_unpin!(Bar<()>); 90 | assert_not_unpin!(Bar); 91 | } 92 | 93 | pub mod cfg_attr { 94 | use std::marker::PhantomPinned; 95 | 96 | use pin_project::pin_project; 97 | 98 | #[cfg_attr(any(), pin_project)] 99 | struct Foo { 100 | f: T, 101 | } 102 | 103 | assert_unpin!(Foo<()>); 104 | assert_not_unpin!(Foo); 105 | 106 | #[cfg_attr(not(any()), pin_project)] 107 | struct Bar { 108 | #[cfg_attr(not(any()), pin)] 109 | f: T, 110 | } 111 | 112 | assert_unpin!(Bar<()>); 113 | assert_not_unpin!(Bar); 114 | } 115 | 116 | // pin_project(!Unpin) 117 | pub mod not_unpin { 118 | use std::marker::PhantomPinned; 119 | 120 | use pin_project::pin_project; 121 | 122 | struct Inner { 123 | f: T, 124 | } 125 | 126 | #[pin_project(!Unpin)] 127 | struct Struct { 128 | #[pin] 129 | inner: Inner, 130 | other: U, 131 | } 132 | 133 | assert_not_unpin!(Struct<(), ()>); 134 | assert_not_unpin!(Struct<(), PhantomPinned>); 135 | assert_not_unpin!(Struct); 136 | assert_not_unpin!(Struct); 137 | 138 | #[pin_project(!Unpin)] 139 | struct TrivialBounds { 140 | #[pin] 141 | f: PhantomPinned, 142 | } 143 | 144 | assert_not_unpin!(TrivialBounds); 145 | 146 | #[pin_project(!Unpin)] 147 | struct PinRef<'a, T, U> { 148 | #[pin] 149 | inner: &'a mut Inner, 150 | other: U, 151 | } 152 | 153 | assert_not_unpin!(PinRef<'_, (), ()>); 154 | } 155 | -------------------------------------------------------------------------------- /examples/enum-default-expanded.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // Original code (./enum-default.rs): 4 | // 5 | // ``` 6 | // #![allow(dead_code)] 7 | // 8 | // use pin_project::pin_project; 9 | // 10 | // #[pin_project(project = EnumProj)] 11 | // enum Enum { 12 | // Pinned(#[pin] T), 13 | // Unpinned(U), 14 | // } 15 | // 16 | // fn main() {} 17 | // ``` 18 | 19 | #![allow( 20 | dead_code, 21 | unused_imports, 22 | unused_parens, 23 | unknown_lints, 24 | renamed_and_removed_lints, 25 | clippy::just_underscores_and_digits, 26 | clippy::needless_lifetimes, 27 | clippy::undocumented_unsafe_blocks, 28 | clippy::used_underscore_binding 29 | )] 30 | 31 | use pin_project::pin_project; 32 | 33 | // #[pin_project(project = EnumProj)] 34 | enum Enum { 35 | Pinned(/* #[pin] */ T), 36 | Unpinned(U), 37 | } 38 | 39 | enum EnumProj<'pin, T, U> 40 | where 41 | Enum: 'pin, 42 | { 43 | Pinned(::pin_project::__private::Pin<&'pin mut (T)>), 44 | Unpinned(&'pin mut (U)), 45 | } 46 | 47 | const _: () = { 48 | // When `#[pin_project]` is used on enums, only named projection types and 49 | // methods are generated because there is no way to access variants of 50 | // projected types without naming it. 51 | // (When `#[pin_project]` is used on structs, both methods are always generated.) 52 | 53 | impl Enum { 54 | fn project<'pin>( 55 | self: ::pin_project::__private::Pin<&'pin mut Self>, 56 | ) -> EnumProj<'pin, T, U> { 57 | unsafe { 58 | match self.get_unchecked_mut() { 59 | Self::Pinned(_0) => { 60 | EnumProj::Pinned(::pin_project::__private::Pin::new_unchecked(_0)) 61 | } 62 | Self::Unpinned(_0) => EnumProj::Unpinned(_0), 63 | } 64 | } 65 | } 66 | } 67 | 68 | // Automatically create the appropriate conditional `Unpin` implementation. 69 | // 70 | // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/53. 71 | // for details. 72 | struct __Enum<'pin, T, U> { 73 | __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin< 74 | 'pin, 75 | (::pin_project::__private::PhantomData, ::pin_project::__private::PhantomData), 76 | >, 77 | __field0: T, 78 | } 79 | impl<'pin, T, U> ::pin_project::__private::Unpin for Enum where 80 | ::pin_project::__private::PinnedFieldsOf<__Enum<'pin, T, U>>: 81 | ::pin_project::__private::Unpin 82 | { 83 | } 84 | // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it. 85 | #[doc(hidden)] 86 | unsafe impl<'pin, T, U> ::pin_project::UnsafeUnpin for Enum where 87 | ::pin_project::__private::PinnedFieldsOf<__Enum<'pin, T, U>>: 88 | ::pin_project::__private::Unpin 89 | { 90 | } 91 | 92 | // Ensure that enum does not implement `Drop`. 93 | // 94 | // See ./struct-default-expanded.rs for details. 95 | trait EnumMustNotImplDrop {} 96 | #[allow(clippy::drop_bounds, drop_bounds)] 97 | impl EnumMustNotImplDrop for T {} 98 | impl EnumMustNotImplDrop for Enum {} 99 | // A dummy impl of `PinnedDrop`, to ensure that users don't accidentally 100 | // write a non-functional `PinnedDrop` impls. 101 | #[doc(hidden)] 102 | impl ::pin_project::__private::PinnedDrop for Enum { 103 | unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} 104 | } 105 | 106 | // We don't need to check for `#[repr(packed)]`, 107 | // since it does not apply to enums. 108 | }; 109 | 110 | fn main() {} 111 | -------------------------------------------------------------------------------- /examples/unsafe_unpin-expanded.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 OR MIT 2 | 3 | // Original code (./unsafe_unpin.rs): 4 | // 5 | // ``` 6 | // #![allow(dead_code)] 7 | // 8 | // use pin_project::{pin_project, UnsafeUnpin}; 9 | // 10 | // #[pin_project(UnsafeUnpin)] 11 | // struct Struct { 12 | // #[pin] 13 | // pinned: T, 14 | // unpinned: U, 15 | // } 16 | // 17 | // unsafe impl UnsafeUnpin for Struct {} 18 | // 19 | // fn main() {} 20 | // ``` 21 | 22 | #![allow( 23 | dead_code, 24 | unused_imports, 25 | unused_parens, 26 | unknown_lints, 27 | renamed_and_removed_lints, 28 | clippy::needless_lifetimes, 29 | clippy::undocumented_unsafe_blocks 30 | )] 31 | 32 | use pin_project::{UnsafeUnpin, pin_project}; 33 | 34 | // #[pin_project(UnsafeUnpin)] 35 | struct Struct { 36 | // #[pin] 37 | pinned: T, 38 | unpinned: U, 39 | } 40 | 41 | const _: () = { 42 | struct __StructProjection<'pin, T, U> 43 | where 44 | Struct: 'pin, 45 | { 46 | pinned: ::pin_project::__private::Pin<&'pin mut (T)>, 47 | unpinned: &'pin mut (U), 48 | } 49 | struct __StructProjectionRef<'pin, T, U> 50 | where 51 | Struct: 'pin, 52 | { 53 | pinned: ::pin_project::__private::Pin<&'pin (T)>, 54 | unpinned: &'pin (U), 55 | } 56 | 57 | impl Struct { 58 | fn project<'pin>( 59 | self: ::pin_project::__private::Pin<&'pin mut Self>, 60 | ) -> __StructProjection<'pin, T, U> { 61 | unsafe { 62 | let Self { pinned, unpinned } = self.get_unchecked_mut(); 63 | __StructProjection { 64 | pinned: ::pin_project::__private::Pin::new_unchecked(pinned), 65 | unpinned, 66 | } 67 | } 68 | } 69 | fn project_ref<'pin>( 70 | self: ::pin_project::__private::Pin<&'pin Self>, 71 | ) -> __StructProjectionRef<'pin, T, U> { 72 | unsafe { 73 | let Self { pinned, unpinned } = self.get_ref(); 74 | __StructProjectionRef { 75 | pinned: ::pin_project::__private::Pin::new_unchecked(pinned), 76 | unpinned, 77 | } 78 | } 79 | } 80 | } 81 | 82 | // Ensure that it's impossible to use pin projections on a #[repr(packed)] 83 | // struct. 84 | // 85 | // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34 86 | // for details. 87 | #[forbid(unaligned_references, safe_packed_borrows)] 88 | fn __assert_not_repr_packed(this: &Struct) { 89 | let _ = &this.pinned; 90 | let _ = &this.unpinned; 91 | } 92 | 93 | // Implement `Unpin` via `UnsafeUnpin`. 94 | impl<'pin, T, U> ::pin_project::__private::Unpin for Struct where 95 | ::pin_project::__private::PinnedFieldsOf<::pin_project::__private::Wrapper<'pin, Self>>: 96 | ::pin_project::UnsafeUnpin 97 | { 98 | } 99 | 100 | // Ensure that struct does not implement `Drop`. 101 | // 102 | // See ./struct-default-expanded.rs for details. 103 | trait StructMustNotImplDrop {} 104 | #[allow(clippy::drop_bounds, drop_bounds)] 105 | impl StructMustNotImplDrop for T {} 106 | impl StructMustNotImplDrop for Struct {} 107 | // A dummy impl of `PinnedDrop`, to ensure that users don't accidentally 108 | // write a non-functional `PinnedDrop` impls. 109 | #[doc(hidden)] 110 | impl ::pin_project::__private::PinnedDrop for Struct { 111 | unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {} 112 | } 113 | }; 114 | 115 | unsafe impl UnsafeUnpin for Struct {} 116 | 117 | fn main() {} 118 | -------------------------------------------------------------------------------- /tests/expand/not_unpin/tuple_struct.expanded.rs: -------------------------------------------------------------------------------- 1 | use pin_project::pin_project; 2 | #[pin(__private(!Unpin))] 3 | struct TupleStruct(#[pin] T, U); 4 | #[allow( 5 | unused_qualifications, 6 | deprecated, 7 | explicit_outlives_requirements, 8 | single_use_lifetimes, 9 | unreachable_pub, 10 | unused_tuple_struct_fields, 11 | clippy::unknown_clippy_lints, 12 | clippy::absolute_paths, 13 | clippy::min_ident_chars, 14 | clippy::pattern_type_mismatch, 15 | clippy::pub_with_shorthand, 16 | clippy::redundant_pub_crate, 17 | clippy::single_char_lifetime_names, 18 | clippy::type_repetition_in_bounds, 19 | clippy::elidable_lifetime_names, 20 | clippy::missing_const_for_fn, 21 | clippy::needless_lifetimes, 22 | clippy::semicolon_if_nothing_returned, 23 | clippy::use_self, 24 | clippy::used_underscore_binding 25 | )] 26 | const _: () = { 27 | #[allow(unused_extern_crates)] 28 | extern crate pin_project as _pin_project; 29 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::mut_mut)] 30 | struct __TupleStructProjection<'pin, T, U>( 31 | ::pin_project::__private::Pin<&'pin mut (T)>, 32 | &'pin mut (U), 33 | ) 34 | where 35 | TupleStruct: 'pin; 36 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::ref_option_ref)] 37 | struct __TupleStructProjectionRef<'pin, T, U>( 38 | ::pin_project::__private::Pin<&'pin (T)>, 39 | &'pin (U), 40 | ) 41 | where 42 | TupleStruct: 'pin; 43 | impl TupleStruct { 44 | #[allow(dead_code)] 45 | #[inline] 46 | fn project<'pin>( 47 | self: _pin_project::__private::Pin<&'pin mut Self>, 48 | ) -> __TupleStructProjection<'pin, T, U> { 49 | unsafe { 50 | let Self(_0, _1) = self.get_unchecked_mut(); 51 | __TupleStructProjection( 52 | _pin_project::__private::Pin::new_unchecked(_0), 53 | _1, 54 | ) 55 | } 56 | } 57 | #[allow(dead_code)] 58 | #[inline] 59 | fn project_ref<'pin>( 60 | self: _pin_project::__private::Pin<&'pin Self>, 61 | ) -> __TupleStructProjectionRef<'pin, T, U> { 62 | unsafe { 63 | let Self(_0, _1) = self.get_ref(); 64 | __TupleStructProjectionRef( 65 | _pin_project::__private::Pin::new_unchecked(_0), 66 | _1, 67 | ) 68 | } 69 | } 70 | } 71 | #[forbid(unaligned_references, safe_packed_borrows)] 72 | fn __assert_not_repr_packed(this: &TupleStruct) { 73 | let _ = &this.0; 74 | let _ = &this.1; 75 | } 76 | #[doc(hidden)] 77 | impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct 78 | where 79 | _pin_project::__private::PinnedFieldsOf< 80 | _pin_project::__private::Wrapper< 81 | 'pin, 82 | _pin_project::__private::PhantomPinned, 83 | >, 84 | >: _pin_project::__private::Unpin, 85 | {} 86 | #[doc(hidden)] 87 | unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct 88 | where 89 | _pin_project::__private::PinnedFieldsOf< 90 | _pin_project::__private::Wrapper< 91 | 'pin, 92 | _pin_project::__private::PhantomPinned, 93 | >, 94 | >: _pin_project::__private::Unpin, 95 | {} 96 | trait TupleStructMustNotImplDrop {} 97 | #[allow(clippy::drop_bounds, drop_bounds)] 98 | impl TupleStructMustNotImplDrop for T {} 99 | impl TupleStructMustNotImplDrop for TupleStruct {} 100 | #[doc(hidden)] 101 | impl _pin_project::__private::PinnedDrop for TupleStruct { 102 | unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} 103 | } 104 | }; 105 | fn main() {} 106 | -------------------------------------------------------------------------------- /tests/expand/not_unpin/struct.expanded.rs: -------------------------------------------------------------------------------- 1 | use pin_project::pin_project; 2 | #[pin(__private(!Unpin))] 3 | struct Struct { 4 | #[pin] 5 | pinned: T, 6 | unpinned: U, 7 | } 8 | #[allow( 9 | unused_qualifications, 10 | deprecated, 11 | explicit_outlives_requirements, 12 | single_use_lifetimes, 13 | unreachable_pub, 14 | unused_tuple_struct_fields, 15 | clippy::unknown_clippy_lints, 16 | clippy::absolute_paths, 17 | clippy::min_ident_chars, 18 | clippy::pattern_type_mismatch, 19 | clippy::pub_with_shorthand, 20 | clippy::redundant_pub_crate, 21 | clippy::single_char_lifetime_names, 22 | clippy::type_repetition_in_bounds, 23 | clippy::elidable_lifetime_names, 24 | clippy::missing_const_for_fn, 25 | clippy::needless_lifetimes, 26 | clippy::semicolon_if_nothing_returned, 27 | clippy::use_self, 28 | clippy::used_underscore_binding 29 | )] 30 | const _: () = { 31 | #[allow(unused_extern_crates)] 32 | extern crate pin_project as _pin_project; 33 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::mut_mut)] 34 | struct __StructProjection<'pin, T, U> 35 | where 36 | Struct: 'pin, 37 | { 38 | pinned: ::pin_project::__private::Pin<&'pin mut (T)>, 39 | unpinned: &'pin mut (U), 40 | } 41 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::ref_option_ref)] 42 | struct __StructProjectionRef<'pin, T, U> 43 | where 44 | Struct: 'pin, 45 | { 46 | pinned: ::pin_project::__private::Pin<&'pin (T)>, 47 | unpinned: &'pin (U), 48 | } 49 | impl Struct { 50 | #[allow(dead_code)] 51 | #[inline] 52 | fn project<'pin>( 53 | self: _pin_project::__private::Pin<&'pin mut Self>, 54 | ) -> __StructProjection<'pin, T, U> { 55 | unsafe { 56 | let Self { pinned, unpinned } = self.get_unchecked_mut(); 57 | __StructProjection { 58 | pinned: _pin_project::__private::Pin::new_unchecked(pinned), 59 | unpinned, 60 | } 61 | } 62 | } 63 | #[allow(dead_code)] 64 | #[inline] 65 | fn project_ref<'pin>( 66 | self: _pin_project::__private::Pin<&'pin Self>, 67 | ) -> __StructProjectionRef<'pin, T, U> { 68 | unsafe { 69 | let Self { pinned, unpinned } = self.get_ref(); 70 | __StructProjectionRef { 71 | pinned: _pin_project::__private::Pin::new_unchecked(pinned), 72 | unpinned, 73 | } 74 | } 75 | } 76 | } 77 | #[forbid(unaligned_references, safe_packed_borrows)] 78 | fn __assert_not_repr_packed(this: &Struct) { 79 | let _ = &this.pinned; 80 | let _ = &this.unpinned; 81 | } 82 | #[doc(hidden)] 83 | impl<'pin, T, U> _pin_project::__private::Unpin for Struct 84 | where 85 | _pin_project::__private::PinnedFieldsOf< 86 | _pin_project::__private::Wrapper< 87 | 'pin, 88 | _pin_project::__private::PhantomPinned, 89 | >, 90 | >: _pin_project::__private::Unpin, 91 | {} 92 | #[doc(hidden)] 93 | unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct 94 | where 95 | _pin_project::__private::PinnedFieldsOf< 96 | _pin_project::__private::Wrapper< 97 | 'pin, 98 | _pin_project::__private::PhantomPinned, 99 | >, 100 | >: _pin_project::__private::Unpin, 101 | {} 102 | trait StructMustNotImplDrop {} 103 | #[allow(clippy::drop_bounds, drop_bounds)] 104 | impl StructMustNotImplDrop for T {} 105 | impl StructMustNotImplDrop for Struct {} 106 | #[doc(hidden)] 107 | impl _pin_project::__private::PinnedDrop for Struct { 108 | unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} 109 | } 110 | }; 111 | fn main() {} 112 | -------------------------------------------------------------------------------- /tests/expand/naming/enum-mut.expanded.rs: -------------------------------------------------------------------------------- 1 | use pin_project::pin_project; 2 | #[pin(__private(project = Proj))] 3 | enum Enum { 4 | Struct { #[pin] pinned: T, unpinned: U }, 5 | Tuple(#[pin] T, U), 6 | Unit, 7 | } 8 | #[allow( 9 | dead_code, 10 | deprecated, 11 | explicit_outlives_requirements, 12 | single_use_lifetimes, 13 | unreachable_pub, 14 | unused_tuple_struct_fields, 15 | clippy::unknown_clippy_lints, 16 | clippy::absolute_paths, 17 | clippy::min_ident_chars, 18 | clippy::pattern_type_mismatch, 19 | clippy::pub_with_shorthand, 20 | clippy::redundant_pub_crate, 21 | clippy::single_char_lifetime_names, 22 | clippy::type_repetition_in_bounds, 23 | clippy::missing_docs_in_private_items, 24 | clippy::mut_mut 25 | )] 26 | enum Proj<'pin, T, U> 27 | where 28 | Enum: 'pin, 29 | { 30 | Struct { 31 | pinned: ::pin_project::__private::Pin<&'pin mut (T)>, 32 | unpinned: &'pin mut (U), 33 | }, 34 | Tuple(::pin_project::__private::Pin<&'pin mut (T)>, &'pin mut (U)), 35 | Unit, 36 | } 37 | #[allow( 38 | unused_qualifications, 39 | deprecated, 40 | explicit_outlives_requirements, 41 | single_use_lifetimes, 42 | unreachable_pub, 43 | unused_tuple_struct_fields, 44 | clippy::unknown_clippy_lints, 45 | clippy::absolute_paths, 46 | clippy::min_ident_chars, 47 | clippy::pattern_type_mismatch, 48 | clippy::pub_with_shorthand, 49 | clippy::redundant_pub_crate, 50 | clippy::single_char_lifetime_names, 51 | clippy::type_repetition_in_bounds, 52 | clippy::elidable_lifetime_names, 53 | clippy::missing_const_for_fn, 54 | clippy::needless_lifetimes, 55 | clippy::semicolon_if_nothing_returned, 56 | clippy::use_self, 57 | clippy::used_underscore_binding 58 | )] 59 | const _: () = { 60 | #[allow(unused_extern_crates)] 61 | extern crate pin_project as _pin_project; 62 | impl Enum { 63 | #[allow(dead_code)] 64 | #[inline] 65 | fn project<'pin>( 66 | self: _pin_project::__private::Pin<&'pin mut Self>, 67 | ) -> Proj<'pin, T, U> { 68 | unsafe { 69 | match self.get_unchecked_mut() { 70 | Self::Struct { pinned, unpinned } => { 71 | Proj::Struct { 72 | pinned: _pin_project::__private::Pin::new_unchecked(pinned), 73 | unpinned, 74 | } 75 | } 76 | Self::Tuple(_0, _1) => { 77 | Proj::Tuple(_pin_project::__private::Pin::new_unchecked(_0), _1) 78 | } 79 | Self::Unit => Proj::Unit, 80 | } 81 | } 82 | } 83 | } 84 | #[allow(missing_debug_implementations, unnameable_types)] 85 | struct __Enum<'pin, T, U> { 86 | __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< 87 | 'pin, 88 | ( 89 | _pin_project::__private::PhantomData, 90 | _pin_project::__private::PhantomData, 91 | ), 92 | >, 93 | __field0: T, 94 | __field1: T, 95 | } 96 | impl<'pin, T, U> _pin_project::__private::Unpin for Enum 97 | where 98 | _pin_project::__private::PinnedFieldsOf< 99 | __Enum<'pin, T, U>, 100 | >: _pin_project::__private::Unpin, 101 | {} 102 | #[doc(hidden)] 103 | unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum 104 | where 105 | _pin_project::__private::PinnedFieldsOf< 106 | __Enum<'pin, T, U>, 107 | >: _pin_project::__private::Unpin, 108 | {} 109 | trait EnumMustNotImplDrop {} 110 | #[allow(clippy::drop_bounds, drop_bounds)] 111 | impl EnumMustNotImplDrop for T {} 112 | impl EnumMustNotImplDrop for Enum {} 113 | #[doc(hidden)] 114 | impl _pin_project::__private::PinnedDrop for Enum { 115 | unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} 116 | } 117 | }; 118 | fn main() {} 119 | -------------------------------------------------------------------------------- /tests/expand/default/tuple_struct.expanded.rs: -------------------------------------------------------------------------------- 1 | use pin_project::pin_project; 2 | #[pin(__private())] 3 | struct TupleStruct(#[pin] T, U); 4 | #[allow( 5 | unused_qualifications, 6 | deprecated, 7 | explicit_outlives_requirements, 8 | single_use_lifetimes, 9 | unreachable_pub, 10 | unused_tuple_struct_fields, 11 | clippy::unknown_clippy_lints, 12 | clippy::absolute_paths, 13 | clippy::min_ident_chars, 14 | clippy::pattern_type_mismatch, 15 | clippy::pub_with_shorthand, 16 | clippy::redundant_pub_crate, 17 | clippy::single_char_lifetime_names, 18 | clippy::type_repetition_in_bounds, 19 | clippy::elidable_lifetime_names, 20 | clippy::missing_const_for_fn, 21 | clippy::needless_lifetimes, 22 | clippy::semicolon_if_nothing_returned, 23 | clippy::use_self, 24 | clippy::used_underscore_binding 25 | )] 26 | const _: () = { 27 | #[allow(unused_extern_crates)] 28 | extern crate pin_project as _pin_project; 29 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::mut_mut)] 30 | struct __TupleStructProjection<'pin, T, U>( 31 | ::pin_project::__private::Pin<&'pin mut (T)>, 32 | &'pin mut (U), 33 | ) 34 | where 35 | TupleStruct: 'pin; 36 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::ref_option_ref)] 37 | struct __TupleStructProjectionRef<'pin, T, U>( 38 | ::pin_project::__private::Pin<&'pin (T)>, 39 | &'pin (U), 40 | ) 41 | where 42 | TupleStruct: 'pin; 43 | impl TupleStruct { 44 | #[allow(dead_code)] 45 | #[inline] 46 | fn project<'pin>( 47 | self: _pin_project::__private::Pin<&'pin mut Self>, 48 | ) -> __TupleStructProjection<'pin, T, U> { 49 | unsafe { 50 | let Self(_0, _1) = self.get_unchecked_mut(); 51 | __TupleStructProjection( 52 | _pin_project::__private::Pin::new_unchecked(_0), 53 | _1, 54 | ) 55 | } 56 | } 57 | #[allow(dead_code)] 58 | #[inline] 59 | fn project_ref<'pin>( 60 | self: _pin_project::__private::Pin<&'pin Self>, 61 | ) -> __TupleStructProjectionRef<'pin, T, U> { 62 | unsafe { 63 | let Self(_0, _1) = self.get_ref(); 64 | __TupleStructProjectionRef( 65 | _pin_project::__private::Pin::new_unchecked(_0), 66 | _1, 67 | ) 68 | } 69 | } 70 | } 71 | #[forbid(unaligned_references, safe_packed_borrows)] 72 | fn __assert_not_repr_packed(this: &TupleStruct) { 73 | let _ = &this.0; 74 | let _ = &this.1; 75 | } 76 | #[allow(missing_debug_implementations, unnameable_types)] 77 | struct __TupleStruct<'pin, T, U> { 78 | __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< 79 | 'pin, 80 | ( 81 | _pin_project::__private::PhantomData, 82 | _pin_project::__private::PhantomData, 83 | ), 84 | >, 85 | __field0: T, 86 | } 87 | impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct 88 | where 89 | _pin_project::__private::PinnedFieldsOf< 90 | __TupleStruct<'pin, T, U>, 91 | >: _pin_project::__private::Unpin, 92 | {} 93 | #[doc(hidden)] 94 | unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct 95 | where 96 | _pin_project::__private::PinnedFieldsOf< 97 | __TupleStruct<'pin, T, U>, 98 | >: _pin_project::__private::Unpin, 99 | {} 100 | trait TupleStructMustNotImplDrop {} 101 | #[allow(clippy::drop_bounds, drop_bounds)] 102 | impl TupleStructMustNotImplDrop for T {} 103 | impl TupleStructMustNotImplDrop for TupleStruct {} 104 | #[doc(hidden)] 105 | impl _pin_project::__private::PinnedDrop for TupleStruct { 106 | unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} 107 | } 108 | }; 109 | fn main() {} 110 | -------------------------------------------------------------------------------- /tests/expand/naming/tuple_struct-none.expanded.rs: -------------------------------------------------------------------------------- 1 | use pin_project::pin_project; 2 | #[pin(__private())] 3 | struct TupleStruct(#[pin] T, U); 4 | #[allow( 5 | unused_qualifications, 6 | deprecated, 7 | explicit_outlives_requirements, 8 | single_use_lifetimes, 9 | unreachable_pub, 10 | unused_tuple_struct_fields, 11 | clippy::unknown_clippy_lints, 12 | clippy::absolute_paths, 13 | clippy::min_ident_chars, 14 | clippy::pattern_type_mismatch, 15 | clippy::pub_with_shorthand, 16 | clippy::redundant_pub_crate, 17 | clippy::single_char_lifetime_names, 18 | clippy::type_repetition_in_bounds, 19 | clippy::elidable_lifetime_names, 20 | clippy::missing_const_for_fn, 21 | clippy::needless_lifetimes, 22 | clippy::semicolon_if_nothing_returned, 23 | clippy::use_self, 24 | clippy::used_underscore_binding 25 | )] 26 | const _: () = { 27 | #[allow(unused_extern_crates)] 28 | extern crate pin_project as _pin_project; 29 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::mut_mut)] 30 | struct __TupleStructProjection<'pin, T, U>( 31 | ::pin_project::__private::Pin<&'pin mut (T)>, 32 | &'pin mut (U), 33 | ) 34 | where 35 | TupleStruct: 'pin; 36 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::ref_option_ref)] 37 | struct __TupleStructProjectionRef<'pin, T, U>( 38 | ::pin_project::__private::Pin<&'pin (T)>, 39 | &'pin (U), 40 | ) 41 | where 42 | TupleStruct: 'pin; 43 | impl TupleStruct { 44 | #[allow(dead_code)] 45 | #[inline] 46 | fn project<'pin>( 47 | self: _pin_project::__private::Pin<&'pin mut Self>, 48 | ) -> __TupleStructProjection<'pin, T, U> { 49 | unsafe { 50 | let Self(_0, _1) = self.get_unchecked_mut(); 51 | __TupleStructProjection( 52 | _pin_project::__private::Pin::new_unchecked(_0), 53 | _1, 54 | ) 55 | } 56 | } 57 | #[allow(dead_code)] 58 | #[inline] 59 | fn project_ref<'pin>( 60 | self: _pin_project::__private::Pin<&'pin Self>, 61 | ) -> __TupleStructProjectionRef<'pin, T, U> { 62 | unsafe { 63 | let Self(_0, _1) = self.get_ref(); 64 | __TupleStructProjectionRef( 65 | _pin_project::__private::Pin::new_unchecked(_0), 66 | _1, 67 | ) 68 | } 69 | } 70 | } 71 | #[forbid(unaligned_references, safe_packed_borrows)] 72 | fn __assert_not_repr_packed(this: &TupleStruct) { 73 | let _ = &this.0; 74 | let _ = &this.1; 75 | } 76 | #[allow(missing_debug_implementations, unnameable_types)] 77 | struct __TupleStruct<'pin, T, U> { 78 | __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< 79 | 'pin, 80 | ( 81 | _pin_project::__private::PhantomData, 82 | _pin_project::__private::PhantomData, 83 | ), 84 | >, 85 | __field0: T, 86 | } 87 | impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct 88 | where 89 | _pin_project::__private::PinnedFieldsOf< 90 | __TupleStruct<'pin, T, U>, 91 | >: _pin_project::__private::Unpin, 92 | {} 93 | #[doc(hidden)] 94 | unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct 95 | where 96 | _pin_project::__private::PinnedFieldsOf< 97 | __TupleStruct<'pin, T, U>, 98 | >: _pin_project::__private::Unpin, 99 | {} 100 | trait TupleStructMustNotImplDrop {} 101 | #[allow(clippy::drop_bounds, drop_bounds)] 102 | impl TupleStructMustNotImplDrop for T {} 103 | impl TupleStructMustNotImplDrop for TupleStruct {} 104 | #[doc(hidden)] 105 | impl _pin_project::__private::PinnedDrop for TupleStruct { 106 | unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} 107 | } 108 | }; 109 | fn main() {} 110 | -------------------------------------------------------------------------------- /tests/expand/naming/enum-ref.expanded.rs: -------------------------------------------------------------------------------- 1 | use pin_project::pin_project; 2 | #[pin(__private(project_ref = ProjRef))] 3 | enum Enum { 4 | Struct { #[pin] pinned: T, unpinned: U }, 5 | Tuple(#[pin] T, U), 6 | Unit, 7 | } 8 | #[allow( 9 | dead_code, 10 | deprecated, 11 | explicit_outlives_requirements, 12 | single_use_lifetimes, 13 | unreachable_pub, 14 | unused_tuple_struct_fields, 15 | clippy::unknown_clippy_lints, 16 | clippy::absolute_paths, 17 | clippy::min_ident_chars, 18 | clippy::pattern_type_mismatch, 19 | clippy::pub_with_shorthand, 20 | clippy::redundant_pub_crate, 21 | clippy::single_char_lifetime_names, 22 | clippy::type_repetition_in_bounds, 23 | clippy::missing_docs_in_private_items, 24 | clippy::ref_option_ref 25 | )] 26 | enum ProjRef<'pin, T, U> 27 | where 28 | Enum: 'pin, 29 | { 30 | Struct { pinned: ::pin_project::__private::Pin<&'pin (T)>, unpinned: &'pin (U) }, 31 | Tuple(::pin_project::__private::Pin<&'pin (T)>, &'pin (U)), 32 | Unit, 33 | } 34 | #[allow( 35 | unused_qualifications, 36 | deprecated, 37 | explicit_outlives_requirements, 38 | single_use_lifetimes, 39 | unreachable_pub, 40 | unused_tuple_struct_fields, 41 | clippy::unknown_clippy_lints, 42 | clippy::absolute_paths, 43 | clippy::min_ident_chars, 44 | clippy::pattern_type_mismatch, 45 | clippy::pub_with_shorthand, 46 | clippy::redundant_pub_crate, 47 | clippy::single_char_lifetime_names, 48 | clippy::type_repetition_in_bounds, 49 | clippy::elidable_lifetime_names, 50 | clippy::missing_const_for_fn, 51 | clippy::needless_lifetimes, 52 | clippy::semicolon_if_nothing_returned, 53 | clippy::use_self, 54 | clippy::used_underscore_binding 55 | )] 56 | const _: () = { 57 | #[allow(unused_extern_crates)] 58 | extern crate pin_project as _pin_project; 59 | impl Enum { 60 | #[allow(dead_code)] 61 | #[inline] 62 | fn project_ref<'pin>( 63 | self: _pin_project::__private::Pin<&'pin Self>, 64 | ) -> ProjRef<'pin, T, U> { 65 | unsafe { 66 | match self.get_ref() { 67 | Self::Struct { pinned, unpinned } => { 68 | ProjRef::Struct { 69 | pinned: _pin_project::__private::Pin::new_unchecked(pinned), 70 | unpinned, 71 | } 72 | } 73 | Self::Tuple(_0, _1) => { 74 | ProjRef::Tuple( 75 | _pin_project::__private::Pin::new_unchecked(_0), 76 | _1, 77 | ) 78 | } 79 | Self::Unit => ProjRef::Unit, 80 | } 81 | } 82 | } 83 | } 84 | #[allow(missing_debug_implementations, unnameable_types)] 85 | struct __Enum<'pin, T, U> { 86 | __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< 87 | 'pin, 88 | ( 89 | _pin_project::__private::PhantomData, 90 | _pin_project::__private::PhantomData, 91 | ), 92 | >, 93 | __field0: T, 94 | __field1: T, 95 | } 96 | impl<'pin, T, U> _pin_project::__private::Unpin for Enum 97 | where 98 | _pin_project::__private::PinnedFieldsOf< 99 | __Enum<'pin, T, U>, 100 | >: _pin_project::__private::Unpin, 101 | {} 102 | #[doc(hidden)] 103 | unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Enum 104 | where 105 | _pin_project::__private::PinnedFieldsOf< 106 | __Enum<'pin, T, U>, 107 | >: _pin_project::__private::Unpin, 108 | {} 109 | trait EnumMustNotImplDrop {} 110 | #[allow(clippy::drop_bounds, drop_bounds)] 111 | impl EnumMustNotImplDrop for T {} 112 | impl EnumMustNotImplDrop for Enum {} 113 | #[doc(hidden)] 114 | impl _pin_project::__private::PinnedDrop for Enum { 115 | unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} 116 | } 117 | }; 118 | fn main() {} 119 | -------------------------------------------------------------------------------- /tests/expand/pub/tuple_struct.expanded.rs: -------------------------------------------------------------------------------- 1 | use pin_project::pin_project; 2 | #[pin(__private())] 3 | pub struct TupleStruct(#[pin] pub T, pub U); 4 | #[allow( 5 | unused_qualifications, 6 | deprecated, 7 | explicit_outlives_requirements, 8 | single_use_lifetimes, 9 | unreachable_pub, 10 | unused_tuple_struct_fields, 11 | clippy::unknown_clippy_lints, 12 | clippy::absolute_paths, 13 | clippy::min_ident_chars, 14 | clippy::pattern_type_mismatch, 15 | clippy::pub_with_shorthand, 16 | clippy::redundant_pub_crate, 17 | clippy::single_char_lifetime_names, 18 | clippy::type_repetition_in_bounds, 19 | clippy::elidable_lifetime_names, 20 | clippy::missing_const_for_fn, 21 | clippy::needless_lifetimes, 22 | clippy::semicolon_if_nothing_returned, 23 | clippy::use_self, 24 | clippy::used_underscore_binding 25 | )] 26 | const _: () = { 27 | #[allow(unused_extern_crates)] 28 | extern crate pin_project as _pin_project; 29 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::mut_mut)] 30 | pub(crate) struct __TupleStructProjection<'pin, T, U>( 31 | pub ::pin_project::__private::Pin<&'pin mut (T)>, 32 | pub &'pin mut (U), 33 | ) 34 | where 35 | TupleStruct: 'pin; 36 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::ref_option_ref)] 37 | pub(crate) struct __TupleStructProjectionRef<'pin, T, U>( 38 | pub ::pin_project::__private::Pin<&'pin (T)>, 39 | pub &'pin (U), 40 | ) 41 | where 42 | TupleStruct: 'pin; 43 | impl TupleStruct { 44 | #[allow(dead_code)] 45 | #[inline] 46 | pub(crate) fn project<'pin>( 47 | self: _pin_project::__private::Pin<&'pin mut Self>, 48 | ) -> __TupleStructProjection<'pin, T, U> { 49 | unsafe { 50 | let Self(_0, _1) = self.get_unchecked_mut(); 51 | __TupleStructProjection( 52 | _pin_project::__private::Pin::new_unchecked(_0), 53 | _1, 54 | ) 55 | } 56 | } 57 | #[allow(dead_code)] 58 | #[inline] 59 | pub(crate) fn project_ref<'pin>( 60 | self: _pin_project::__private::Pin<&'pin Self>, 61 | ) -> __TupleStructProjectionRef<'pin, T, U> { 62 | unsafe { 63 | let Self(_0, _1) = self.get_ref(); 64 | __TupleStructProjectionRef( 65 | _pin_project::__private::Pin::new_unchecked(_0), 66 | _1, 67 | ) 68 | } 69 | } 70 | } 71 | #[forbid(unaligned_references, safe_packed_borrows)] 72 | fn __assert_not_repr_packed(this: &TupleStruct) { 73 | let _ = &this.0; 74 | let _ = &this.1; 75 | } 76 | #[allow(missing_debug_implementations, unnameable_types)] 77 | pub struct __TupleStruct<'pin, T, U> { 78 | __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< 79 | 'pin, 80 | ( 81 | _pin_project::__private::PhantomData, 82 | _pin_project::__private::PhantomData, 83 | ), 84 | >, 85 | __field0: T, 86 | } 87 | impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct 88 | where 89 | _pin_project::__private::PinnedFieldsOf< 90 | __TupleStruct<'pin, T, U>, 91 | >: _pin_project::__private::Unpin, 92 | {} 93 | #[doc(hidden)] 94 | unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct 95 | where 96 | _pin_project::__private::PinnedFieldsOf< 97 | __TupleStruct<'pin, T, U>, 98 | >: _pin_project::__private::Unpin, 99 | {} 100 | trait TupleStructMustNotImplDrop {} 101 | #[allow(clippy::drop_bounds, drop_bounds)] 102 | impl TupleStructMustNotImplDrop for T {} 103 | impl TupleStructMustNotImplDrop for TupleStruct {} 104 | #[doc(hidden)] 105 | impl _pin_project::__private::PinnedDrop for TupleStruct { 106 | unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} 107 | } 108 | }; 109 | fn main() {} 110 | -------------------------------------------------------------------------------- /tests/expand/default/struct.expanded.rs: -------------------------------------------------------------------------------- 1 | use pin_project::pin_project; 2 | #[pin(__private())] 3 | struct Struct { 4 | #[pin] 5 | pinned: T, 6 | unpinned: U, 7 | } 8 | #[allow( 9 | unused_qualifications, 10 | deprecated, 11 | explicit_outlives_requirements, 12 | single_use_lifetimes, 13 | unreachable_pub, 14 | unused_tuple_struct_fields, 15 | clippy::unknown_clippy_lints, 16 | clippy::absolute_paths, 17 | clippy::min_ident_chars, 18 | clippy::pattern_type_mismatch, 19 | clippy::pub_with_shorthand, 20 | clippy::redundant_pub_crate, 21 | clippy::single_char_lifetime_names, 22 | clippy::type_repetition_in_bounds, 23 | clippy::elidable_lifetime_names, 24 | clippy::missing_const_for_fn, 25 | clippy::needless_lifetimes, 26 | clippy::semicolon_if_nothing_returned, 27 | clippy::use_self, 28 | clippy::used_underscore_binding 29 | )] 30 | const _: () = { 31 | #[allow(unused_extern_crates)] 32 | extern crate pin_project as _pin_project; 33 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::mut_mut)] 34 | struct __StructProjection<'pin, T, U> 35 | where 36 | Struct: 'pin, 37 | { 38 | pinned: ::pin_project::__private::Pin<&'pin mut (T)>, 39 | unpinned: &'pin mut (U), 40 | } 41 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::ref_option_ref)] 42 | struct __StructProjectionRef<'pin, T, U> 43 | where 44 | Struct: 'pin, 45 | { 46 | pinned: ::pin_project::__private::Pin<&'pin (T)>, 47 | unpinned: &'pin (U), 48 | } 49 | impl Struct { 50 | #[allow(dead_code)] 51 | #[inline] 52 | fn project<'pin>( 53 | self: _pin_project::__private::Pin<&'pin mut Self>, 54 | ) -> __StructProjection<'pin, T, U> { 55 | unsafe { 56 | let Self { pinned, unpinned } = self.get_unchecked_mut(); 57 | __StructProjection { 58 | pinned: _pin_project::__private::Pin::new_unchecked(pinned), 59 | unpinned, 60 | } 61 | } 62 | } 63 | #[allow(dead_code)] 64 | #[inline] 65 | fn project_ref<'pin>( 66 | self: _pin_project::__private::Pin<&'pin Self>, 67 | ) -> __StructProjectionRef<'pin, T, U> { 68 | unsafe { 69 | let Self { pinned, unpinned } = self.get_ref(); 70 | __StructProjectionRef { 71 | pinned: _pin_project::__private::Pin::new_unchecked(pinned), 72 | unpinned, 73 | } 74 | } 75 | } 76 | } 77 | #[forbid(unaligned_references, safe_packed_borrows)] 78 | fn __assert_not_repr_packed(this: &Struct) { 79 | let _ = &this.pinned; 80 | let _ = &this.unpinned; 81 | } 82 | #[allow(missing_debug_implementations, unnameable_types)] 83 | struct __Struct<'pin, T, U> { 84 | __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< 85 | 'pin, 86 | ( 87 | _pin_project::__private::PhantomData, 88 | _pin_project::__private::PhantomData, 89 | ), 90 | >, 91 | __field0: T, 92 | } 93 | impl<'pin, T, U> _pin_project::__private::Unpin for Struct 94 | where 95 | _pin_project::__private::PinnedFieldsOf< 96 | __Struct<'pin, T, U>, 97 | >: _pin_project::__private::Unpin, 98 | {} 99 | #[doc(hidden)] 100 | unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct 101 | where 102 | _pin_project::__private::PinnedFieldsOf< 103 | __Struct<'pin, T, U>, 104 | >: _pin_project::__private::Unpin, 105 | {} 106 | trait StructMustNotImplDrop {} 107 | #[allow(clippy::drop_bounds, drop_bounds)] 108 | impl StructMustNotImplDrop for T {} 109 | impl StructMustNotImplDrop for Struct {} 110 | #[doc(hidden)] 111 | impl _pin_project::__private::PinnedDrop for Struct { 112 | unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} 113 | } 114 | }; 115 | fn main() {} 116 | -------------------------------------------------------------------------------- /tests/expand/naming/struct-none.expanded.rs: -------------------------------------------------------------------------------- 1 | use pin_project::pin_project; 2 | #[pin(__private())] 3 | struct Struct { 4 | #[pin] 5 | pinned: T, 6 | unpinned: U, 7 | } 8 | #[allow( 9 | unused_qualifications, 10 | deprecated, 11 | explicit_outlives_requirements, 12 | single_use_lifetimes, 13 | unreachable_pub, 14 | unused_tuple_struct_fields, 15 | clippy::unknown_clippy_lints, 16 | clippy::absolute_paths, 17 | clippy::min_ident_chars, 18 | clippy::pattern_type_mismatch, 19 | clippy::pub_with_shorthand, 20 | clippy::redundant_pub_crate, 21 | clippy::single_char_lifetime_names, 22 | clippy::type_repetition_in_bounds, 23 | clippy::elidable_lifetime_names, 24 | clippy::missing_const_for_fn, 25 | clippy::needless_lifetimes, 26 | clippy::semicolon_if_nothing_returned, 27 | clippy::use_self, 28 | clippy::used_underscore_binding 29 | )] 30 | const _: () = { 31 | #[allow(unused_extern_crates)] 32 | extern crate pin_project as _pin_project; 33 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::mut_mut)] 34 | struct __StructProjection<'pin, T, U> 35 | where 36 | Struct: 'pin, 37 | { 38 | pinned: ::pin_project::__private::Pin<&'pin mut (T)>, 39 | unpinned: &'pin mut (U), 40 | } 41 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::ref_option_ref)] 42 | struct __StructProjectionRef<'pin, T, U> 43 | where 44 | Struct: 'pin, 45 | { 46 | pinned: ::pin_project::__private::Pin<&'pin (T)>, 47 | unpinned: &'pin (U), 48 | } 49 | impl Struct { 50 | #[allow(dead_code)] 51 | #[inline] 52 | fn project<'pin>( 53 | self: _pin_project::__private::Pin<&'pin mut Self>, 54 | ) -> __StructProjection<'pin, T, U> { 55 | unsafe { 56 | let Self { pinned, unpinned } = self.get_unchecked_mut(); 57 | __StructProjection { 58 | pinned: _pin_project::__private::Pin::new_unchecked(pinned), 59 | unpinned, 60 | } 61 | } 62 | } 63 | #[allow(dead_code)] 64 | #[inline] 65 | fn project_ref<'pin>( 66 | self: _pin_project::__private::Pin<&'pin Self>, 67 | ) -> __StructProjectionRef<'pin, T, U> { 68 | unsafe { 69 | let Self { pinned, unpinned } = self.get_ref(); 70 | __StructProjectionRef { 71 | pinned: _pin_project::__private::Pin::new_unchecked(pinned), 72 | unpinned, 73 | } 74 | } 75 | } 76 | } 77 | #[forbid(unaligned_references, safe_packed_borrows)] 78 | fn __assert_not_repr_packed(this: &Struct) { 79 | let _ = &this.pinned; 80 | let _ = &this.unpinned; 81 | } 82 | #[allow(missing_debug_implementations, unnameable_types)] 83 | struct __Struct<'pin, T, U> { 84 | __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< 85 | 'pin, 86 | ( 87 | _pin_project::__private::PhantomData, 88 | _pin_project::__private::PhantomData, 89 | ), 90 | >, 91 | __field0: T, 92 | } 93 | impl<'pin, T, U> _pin_project::__private::Unpin for Struct 94 | where 95 | _pin_project::__private::PinnedFieldsOf< 96 | __Struct<'pin, T, U>, 97 | >: _pin_project::__private::Unpin, 98 | {} 99 | #[doc(hidden)] 100 | unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct 101 | where 102 | _pin_project::__private::PinnedFieldsOf< 103 | __Struct<'pin, T, U>, 104 | >: _pin_project::__private::Unpin, 105 | {} 106 | trait StructMustNotImplDrop {} 107 | #[allow(clippy::drop_bounds, drop_bounds)] 108 | impl StructMustNotImplDrop for T {} 109 | impl StructMustNotImplDrop for Struct {} 110 | #[doc(hidden)] 111 | impl _pin_project::__private::PinnedDrop for Struct { 112 | unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} 113 | } 114 | }; 115 | fn main() {} 116 | -------------------------------------------------------------------------------- /tests/expand/pub/struct.expanded.rs: -------------------------------------------------------------------------------- 1 | use pin_project::pin_project; 2 | #[pin(__private())] 3 | pub struct Struct { 4 | #[pin] 5 | pub pinned: T, 6 | pub unpinned: U, 7 | } 8 | #[allow( 9 | unused_qualifications, 10 | deprecated, 11 | explicit_outlives_requirements, 12 | single_use_lifetimes, 13 | unreachable_pub, 14 | unused_tuple_struct_fields, 15 | clippy::unknown_clippy_lints, 16 | clippy::absolute_paths, 17 | clippy::min_ident_chars, 18 | clippy::pattern_type_mismatch, 19 | clippy::pub_with_shorthand, 20 | clippy::redundant_pub_crate, 21 | clippy::single_char_lifetime_names, 22 | clippy::type_repetition_in_bounds, 23 | clippy::elidable_lifetime_names, 24 | clippy::missing_const_for_fn, 25 | clippy::needless_lifetimes, 26 | clippy::semicolon_if_nothing_returned, 27 | clippy::use_self, 28 | clippy::used_underscore_binding 29 | )] 30 | const _: () = { 31 | #[allow(unused_extern_crates)] 32 | extern crate pin_project as _pin_project; 33 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::mut_mut)] 34 | pub(crate) struct __StructProjection<'pin, T, U> 35 | where 36 | Struct: 'pin, 37 | { 38 | pub pinned: ::pin_project::__private::Pin<&'pin mut (T)>, 39 | pub unpinned: &'pin mut (U), 40 | } 41 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::ref_option_ref)] 42 | pub(crate) struct __StructProjectionRef<'pin, T, U> 43 | where 44 | Struct: 'pin, 45 | { 46 | pub pinned: ::pin_project::__private::Pin<&'pin (T)>, 47 | pub unpinned: &'pin (U), 48 | } 49 | impl Struct { 50 | #[allow(dead_code)] 51 | #[inline] 52 | pub(crate) fn project<'pin>( 53 | self: _pin_project::__private::Pin<&'pin mut Self>, 54 | ) -> __StructProjection<'pin, T, U> { 55 | unsafe { 56 | let Self { pinned, unpinned } = self.get_unchecked_mut(); 57 | __StructProjection { 58 | pinned: _pin_project::__private::Pin::new_unchecked(pinned), 59 | unpinned, 60 | } 61 | } 62 | } 63 | #[allow(dead_code)] 64 | #[inline] 65 | pub(crate) fn project_ref<'pin>( 66 | self: _pin_project::__private::Pin<&'pin Self>, 67 | ) -> __StructProjectionRef<'pin, T, U> { 68 | unsafe { 69 | let Self { pinned, unpinned } = self.get_ref(); 70 | __StructProjectionRef { 71 | pinned: _pin_project::__private::Pin::new_unchecked(pinned), 72 | unpinned, 73 | } 74 | } 75 | } 76 | } 77 | #[forbid(unaligned_references, safe_packed_borrows)] 78 | fn __assert_not_repr_packed(this: &Struct) { 79 | let _ = &this.pinned; 80 | let _ = &this.unpinned; 81 | } 82 | #[allow(missing_debug_implementations, unnameable_types)] 83 | pub struct __Struct<'pin, T, U> { 84 | __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< 85 | 'pin, 86 | ( 87 | _pin_project::__private::PhantomData, 88 | _pin_project::__private::PhantomData, 89 | ), 90 | >, 91 | __field0: T, 92 | } 93 | impl<'pin, T, U> _pin_project::__private::Unpin for Struct 94 | where 95 | _pin_project::__private::PinnedFieldsOf< 96 | __Struct<'pin, T, U>, 97 | >: _pin_project::__private::Unpin, 98 | {} 99 | #[doc(hidden)] 100 | unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for Struct 101 | where 102 | _pin_project::__private::PinnedFieldsOf< 103 | __Struct<'pin, T, U>, 104 | >: _pin_project::__private::Unpin, 105 | {} 106 | trait StructMustNotImplDrop {} 107 | #[allow(clippy::drop_bounds, drop_bounds)] 108 | impl StructMustNotImplDrop for T {} 109 | impl StructMustNotImplDrop for Struct {} 110 | #[doc(hidden)] 111 | impl _pin_project::__private::PinnedDrop for Struct { 112 | unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} 113 | } 114 | }; 115 | fn main() {} 116 | -------------------------------------------------------------------------------- /tests/expand/naming/tuple_struct-mut.expanded.rs: -------------------------------------------------------------------------------- 1 | use pin_project::pin_project; 2 | #[pin(__private(project = Proj))] 3 | struct TupleStruct(#[pin] T, U); 4 | #[allow( 5 | dead_code, 6 | deprecated, 7 | explicit_outlives_requirements, 8 | single_use_lifetimes, 9 | unreachable_pub, 10 | unused_tuple_struct_fields, 11 | clippy::unknown_clippy_lints, 12 | clippy::absolute_paths, 13 | clippy::min_ident_chars, 14 | clippy::pattern_type_mismatch, 15 | clippy::pub_with_shorthand, 16 | clippy::redundant_pub_crate, 17 | clippy::single_char_lifetime_names, 18 | clippy::type_repetition_in_bounds, 19 | clippy::missing_docs_in_private_items, 20 | clippy::mut_mut 21 | )] 22 | struct Proj<'pin, T, U>( 23 | ::pin_project::__private::Pin<&'pin mut (T)>, 24 | &'pin mut (U), 25 | ) 26 | where 27 | TupleStruct: 'pin; 28 | #[allow( 29 | unused_qualifications, 30 | deprecated, 31 | explicit_outlives_requirements, 32 | single_use_lifetimes, 33 | unreachable_pub, 34 | unused_tuple_struct_fields, 35 | clippy::unknown_clippy_lints, 36 | clippy::absolute_paths, 37 | clippy::min_ident_chars, 38 | clippy::pattern_type_mismatch, 39 | clippy::pub_with_shorthand, 40 | clippy::redundant_pub_crate, 41 | clippy::single_char_lifetime_names, 42 | clippy::type_repetition_in_bounds, 43 | clippy::elidable_lifetime_names, 44 | clippy::missing_const_for_fn, 45 | clippy::needless_lifetimes, 46 | clippy::semicolon_if_nothing_returned, 47 | clippy::use_self, 48 | clippy::used_underscore_binding 49 | )] 50 | const _: () = { 51 | #[allow(unused_extern_crates)] 52 | extern crate pin_project as _pin_project; 53 | #[allow(dead_code, clippy::missing_docs_in_private_items, clippy::ref_option_ref)] 54 | struct __TupleStructProjectionRef<'pin, T, U>( 55 | ::pin_project::__private::Pin<&'pin (T)>, 56 | &'pin (U), 57 | ) 58 | where 59 | TupleStruct: 'pin; 60 | impl TupleStruct { 61 | #[allow(dead_code)] 62 | #[inline] 63 | fn project<'pin>( 64 | self: _pin_project::__private::Pin<&'pin mut Self>, 65 | ) -> Proj<'pin, T, U> { 66 | unsafe { 67 | let Self(_0, _1) = self.get_unchecked_mut(); 68 | Proj(_pin_project::__private::Pin::new_unchecked(_0), _1) 69 | } 70 | } 71 | #[allow(dead_code)] 72 | #[inline] 73 | fn project_ref<'pin>( 74 | self: _pin_project::__private::Pin<&'pin Self>, 75 | ) -> __TupleStructProjectionRef<'pin, T, U> { 76 | unsafe { 77 | let Self(_0, _1) = self.get_ref(); 78 | __TupleStructProjectionRef( 79 | _pin_project::__private::Pin::new_unchecked(_0), 80 | _1, 81 | ) 82 | } 83 | } 84 | } 85 | #[forbid(unaligned_references, safe_packed_borrows)] 86 | fn __assert_not_repr_packed(this: &TupleStruct) { 87 | let _ = &this.0; 88 | let _ = &this.1; 89 | } 90 | #[allow(missing_debug_implementations, unnameable_types)] 91 | struct __TupleStruct<'pin, T, U> { 92 | __pin_project_use_generics: _pin_project::__private::AlwaysUnpin< 93 | 'pin, 94 | ( 95 | _pin_project::__private::PhantomData, 96 | _pin_project::__private::PhantomData, 97 | ), 98 | >, 99 | __field0: T, 100 | } 101 | impl<'pin, T, U> _pin_project::__private::Unpin for TupleStruct 102 | where 103 | _pin_project::__private::PinnedFieldsOf< 104 | __TupleStruct<'pin, T, U>, 105 | >: _pin_project::__private::Unpin, 106 | {} 107 | #[doc(hidden)] 108 | unsafe impl<'pin, T, U> _pin_project::UnsafeUnpin for TupleStruct 109 | where 110 | _pin_project::__private::PinnedFieldsOf< 111 | __TupleStruct<'pin, T, U>, 112 | >: _pin_project::__private::Unpin, 113 | {} 114 | trait TupleStructMustNotImplDrop {} 115 | #[allow(clippy::drop_bounds, drop_bounds)] 116 | impl TupleStructMustNotImplDrop for T {} 117 | impl TupleStructMustNotImplDrop for TupleStruct {} 118 | #[doc(hidden)] 119 | impl _pin_project::__private::PinnedDrop for TupleStruct { 120 | unsafe fn drop(self: _pin_project::__private::Pin<&mut Self>) {} 121 | } 122 | }; 123 | fn main() {} 124 | --------------------------------------------------------------------------------