aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Galenson <jgalenson@google.com>2020-10-06 21:45:46 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-10-06 21:45:46 +0000
commit8e2f837c592ce7fce0eb35c54048f1433bb8da4e (patch)
tree2b05583cf437a2388364b8f684c187c0528b66a3
parentfea1d3e4f2bd05c6f081c7fa1a699635c4969c86 (diff)
parent9553c68a9bd4f07cb59f0db99a88b4de3b1d40f2 (diff)
downloadpin-project-lite-8e2f837c592ce7fce0eb35c54048f1433bb8da4e.tar.gz
Import pin-project-lite-0.1.7 am: 9103268fc2 am: 35a98885de am: 2634916265 am: 9553c68a9b
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/pin-project-lite/+/1449015 Change-Id: I3e150755fb0c39d8dd4562135842da96e9049639
-rw-r--r--.cargo_vcs_info.json5
-rw-r--r--.editorconfig16
-rw-r--r--.gitattributes4
-rw-r--r--.github/CODEOWNERS1
-rw-r--r--.github/bors.toml2
-rw-r--r--.github/workflows/ci.yml132
-rw-r--r--.gitignore6
-rw-r--r--CHANGELOG.md72
-rw-r--r--Cargo.toml34
-rw-r--r--Cargo.toml.orig31
-rw-r--r--LICENSE-APACHE202
-rw-r--r--LICENSE-MIT23
-rw-r--r--README.md109
-rw-r--r--ci/check-minimal-versions.sh27
-rw-r--r--ci/install-component.sh22
-rw-r--r--ci/install-rust.sh13
-rw-r--r--rustfmt.toml25
-rw-r--r--src/lib.rs745
-rw-r--r--tests/compiletest.rs8
-rw-r--r--tests/include/basic.rs10
-rw-r--r--tests/lint.rs90
-rw-r--r--tests/lint.txt138
-rw-r--r--tests/test.rs384
-rw-r--r--tests/ui/conflict-drop.rs15
-rw-r--r--tests/ui/conflict-drop.stderr16
-rw-r--r--tests/ui/conflict-unpin.rs40
-rw-r--r--tests/ui/conflict-unpin.stderr50
-rw-r--r--tests/ui/invalid-bounds.rs93
-rw-r--r--tests/ui/invalid-bounds.stderr134
-rw-r--r--tests/ui/invalid.rs25
-rw-r--r--tests/ui/invalid.stderr17
-rw-r--r--tests/ui/overlapping_lifetime_names.rs10
-rw-r--r--tests/ui/overlapping_lifetime_names.stderr75
-rw-r--r--tests/ui/overlapping_unpin_struct.rs19
-rw-r--r--tests/ui/overlapping_unpin_struct.stderr11
-rw-r--r--tests/ui/packed.rs19
-rw-r--r--tests/ui/packed.stderr55
-rw-r--r--tests/ui/proper_unpin.rs41
-rw-r--r--tests/ui/proper_unpin.stderr37
-rw-r--r--tests/ui/unpin_sneaky.rs12
-rw-r--r--tests/ui/unpin_sneaky.stderr11
-rw-r--r--tests/ui/unsupported.rs27
-rw-r--r--tests/ui/unsupported.stderr29
43 files changed, 2835 insertions, 0 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644
index 0000000..416a9fb
--- /dev/null
+++ b/.cargo_vcs_info.json
@@ -0,0 +1,5 @@
+{
+ "git": {
+ "sha1": "5859acd41133d479638abccea409ac0f64b0ef77"
+ }
+}
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..c93ffc7
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,16 @@
+# EditorConfig configuration
+# https://editorconfig.org
+
+# Top-most EditorConfig file
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+charset = utf-8
+indent_style = space
+indent_size = 4
+
+[*.{json,yml,md}]
+indent_size = 2
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..45bca84
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,4 @@
+[attr]rust text eol=lf whitespace=tab-in-indent,trailing-space,tabwidth=4
+
+* text=auto eol=lf
+*.rs rust
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..2fdc28f
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1 @@
+* @taiki-e
diff --git a/.github/bors.toml b/.github/bors.toml
new file mode 100644
index 0000000..1779788
--- /dev/null
+++ b/.github/bors.toml
@@ -0,0 +1,2 @@
+status = ["ci"]
+delete_merged_branches = true
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..329896b
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,132 @@
+name: CI
+
+on:
+ pull_request:
+ push:
+ branches:
+ - master
+ - staging
+ - trying
+ schedule:
+ - cron: '00 01 * * *'
+
+env:
+ RUSTFLAGS: -Dwarnings
+ RUST_BACKTRACE: 1
+
+defaults:
+ run:
+ shell: bash
+
+jobs:
+ test:
+ name: test
+ strategy:
+ matrix:
+ rust:
+ # This is the minimum supported Rust version of this crate.
+ # When updating this, the reminder to update the minimum supported Rust version in README.md.
+ - 1.37.0
+ - stable
+ - beta
+ - nightly
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Install Rust
+ run: |
+ . ./ci/install-rust.sh ${{ matrix.rust }}
+ - name: Install cargo-hack
+ if: matrix.rust == 'nightly'
+ run: |
+ cargo install cargo-hack
+ - name: Add targets
+ if: matrix.rust == 'nightly'
+ run: |
+ rustup target add thumbv7m-none-eabi
+ - name: cargo test
+ run: |
+ cargo test --all
+ - name: cargo check (no-std)
+ if: matrix.rust == 'nightly'
+ run: |
+ cargo check --target thumbv7m-none-eabi --manifest-path tests/no-std/Cargo.toml
+ - name: cargo check (minimal versions)
+ if: matrix.rust == 'nightly'
+ run: |
+ . ./ci/check-minimal-versions.sh
+
+ clippy:
+ name: clippy
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Install Rust
+ run: |
+ . ./ci/install-rust.sh
+ - name: Install clippy
+ run: |
+ . ./ci/install-component.sh clippy
+ - name: cargo clippy
+ run: |
+ cargo clippy --all --all-features --all-targets
+
+ rustfmt:
+ name: rustfmt
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Install Rust
+ run: |
+ . ./ci/install-rust.sh
+ - name: Install rustfmt
+ run: |
+ . ./ci/install-component.sh rustfmt
+ - name: cargo fmt --check
+ run: |
+ cargo fmt --all -- --check
+
+ rustdoc:
+ name: rustdoc
+ env:
+ RUSTDOCFLAGS: -Dwarnings
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Install Rust
+ run: |
+ . ./ci/install-rust.sh
+ - name: cargo doc
+ run: |
+ cargo doc --no-deps --all --all-features
+
+ # These jobs don't actually test anything, but they're used to tell bors the
+ # build completed, as there is no practical way to detect when a workflow is
+ # successful listening to webhooks only.
+ #
+ # ALL THE PREVIOUS JOBS NEEDS TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
+
+ ci-success:
+ name: ci
+ if: github.event_name == 'push' && success()
+ needs:
+ - test
+ - clippy
+ - rustfmt
+ - rustdoc
+ runs-on: ubuntu-latest
+ steps:
+ - name: Mark the job as a success
+ run: exit 0
+ ci-failure:
+ name: ci
+ if: github.event_name == 'push' && !success()
+ needs:
+ - test
+ - clippy
+ - rustfmt
+ - rustdoc
+ runs-on: ubuntu-latest
+ steps:
+ - name: Mark the job as a failure
+ run: exit 1
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..214d7a8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+target
+Cargo.lock
+
+# For platform and editor specific settings, it is recommended to add to
+# a global .gitignore file.
+# Refs: https://help.github.com/en/articles/ignoring-files#create-a-global-gitignore
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..17b1f87
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,72 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+This project adheres to [Semantic Versioning](https://semver.org).
+
+## [Unreleased]
+
+## [0.1.7] - 2020-06-04
+
+* [Support `?Sized` bounds in where clauses.][22]
+
+* [Fix lifetime inference error when an associated type is used in fields.][20]
+
+* Suppress `clippy::used_underscore_binding` lint in generated code.
+
+* Documentation improvements.
+
+[20]: https://github.com/taiki-e/pin-project-lite/pull/20
+[22]: https://github.com/taiki-e/pin-project-lite/pull/22
+
+## [0.1.6] - 2020-05-31
+
+* [Support lifetime bounds in where clauses.][18]
+
+* Documentation improvements.
+
+[18]: https://github.com/taiki-e/pin-project-lite/pull/18
+
+## [0.1.5] - 2020-05-07
+
+* [Support overwriting the name of core crate.][14]
+
+[14]: https://github.com/taiki-e/pin-project-lite/pull/14
+
+## [0.1.4] - 2020-01-20
+
+* [Support ?Sized bounds in generic parameters.][9]
+
+[9]: https://github.com/taiki-e/pin-project-lite/pull/9
+
+## [0.1.3] - 2020-01-20
+
+* [Support lifetime bounds in generic parameters.][7]
+
+[7]: https://github.com/taiki-e/pin-project-lite/pull/7
+
+## [0.1.2] - 2020-01-05
+
+* [Support recognizing default generic parameters.][6]
+
+[6]: https://github.com/taiki-e/pin-project-lite/pull/6
+
+## [0.1.1] - 2019-11-15
+
+* [`pin_project!` macro now determines the visibility of the projection type/method is based on the original type.][5]
+
+[5]: https://github.com/taiki-e/pin-project-lite/pull/5
+
+## [0.1.0] - 2019-10-22
+
+Initial release
+
+[Unreleased]: https://github.com/taiki-e/pin-project-lite/compare/v0.1.7...HEAD
+[0.1.7]: https://github.com/taiki-e/pin-project-lite/compare/v0.1.6...v0.1.7
+[0.1.6]: https://github.com/taiki-e/pin-project-lite/compare/v0.1.5...v0.1.6
+[0.1.5]: https://github.com/taiki-e/pin-project-lite/compare/v0.1.4...v0.1.5
+[0.1.4]: https://github.com/taiki-e/pin-project-lite/compare/v0.1.3...v0.1.4
+[0.1.3]: https://github.com/taiki-e/pin-project-lite/compare/v0.1.2...v0.1.3
+[0.1.2]: https://github.com/taiki-e/pin-project-lite/compare/v0.1.1...v0.1.2
+[0.1.1]: https://github.com/taiki-e/pin-project-lite/compare/v0.1.0...v0.1.1
+[0.1.0]: https://github.com/taiki-e/pin-project-lite/releases/tag/v0.1.0
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..cd34113
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,34 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "pin-project-lite"
+version = "0.1.7"
+authors = ["Taiki Endo <te316e89@gmail.com>"]
+description = "A lightweight version of pin-project written with declarative macros.\n"
+homepage = "https://github.com/taiki-e/pin-project-lite"
+documentation = "https://docs.rs/pin-project-lite"
+readme = "README.md"
+keywords = ["pin", "macros"]
+categories = ["no-std", "rust-patterns"]
+license = "Apache-2.0 OR MIT"
+repository = "https://github.com/taiki-e/pin-project-lite"
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[dependencies]
+[dev-dependencies.rustversion]
+version = "1.0"
+
+[dev-dependencies.trybuild]
+version = "1.0"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644
index 0000000..4d42294
--- /dev/null
+++ b/Cargo.toml.orig
@@ -0,0 +1,31 @@
+[package]
+name = "pin-project-lite"
+version = "0.1.7"
+authors = ["Taiki Endo <te316e89@gmail.com>"]
+edition = "2018"
+license = "Apache-2.0 OR MIT"
+repository = "https://github.com/taiki-e/pin-project-lite"
+homepage = "https://github.com/taiki-e/pin-project-lite"
+documentation = "https://docs.rs/pin-project-lite"
+keywords = ["pin", "macros"]
+categories = ["no-std", "rust-patterns"]
+readme = "README.md"
+description = """
+A lightweight version of pin-project written with declarative macros.
+"""
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[workspace]
+members = [
+ "tests/doc",
+ "tests/no-core",
+ "tests/no-std",
+]
+
+[dependencies]
+
+[dev-dependencies]
+rustversion = "1.0"
+trybuild = "1.0"
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE-APACHE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/LICENSE-MIT b/LICENSE-MIT
new file mode 100644
index 0000000..31aa793
--- /dev/null
+++ b/LICENSE-MIT
@@ -0,0 +1,23 @@
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..faec117
--- /dev/null
+++ b/README.md
@@ -0,0 +1,109 @@
+# pin-project-lite
+
+[![crates-badge]][crates-url]
+[![docs-badge]][docs-url]
+[![license-badge]][license]
+[![rustc-badge]][rustc-url]
+
+[crates-badge]: https://img.shields.io/crates/v/pin-project-lite.svg
+[crates-url]: https://crates.io/crates/pin-project-lite
+[docs-badge]: https://docs.rs/pin-project-lite/badge.svg
+[docs-url]: https://docs.rs/pin-project-lite
+[license-badge]: https://img.shields.io/badge/license-Apache--2.0%20OR%20MIT-blue.svg
+[license]: #license
+[rustc-badge]: https://img.shields.io/badge/rustc-1.37+-lightgray.svg
+[rustc-url]: https://blog.rust-lang.org/2019/08/15/Rust-1.37.0.html
+
+A lightweight version of [pin-project] written with declarative macros.
+
+## Usage
+
+Add this to your `Cargo.toml`:
+
+```toml
+[dependencies]
+pin-project-lite = "0.1"
+```
+
+The current pin-project-lite requires Rust 1.37 or later.
+
+## Examples
+
+[`pin_project!`] macro creates a projection type covering all the fields of struct.
+
+```rust
+use pin_project_lite::pin_project;
+use std::pin::Pin;
+
+pin_project! {
+ struct Struct<T, U> {
+ #[pin]
+ pinned: T,
+ unpinned: U,
+ }
+}
+
+impl<T, U> Struct<T, U> {
+ fn method(self: Pin<&mut Self>) {
+ let this = self.project();
+ let _: Pin<&mut T> = this.pinned; // Pinned reference to the field
+ let _: &mut U = this.unpinned; // Normal reference to the field
+ }
+}
+```
+
+## [pin-project] vs pin-project-lite
+
+Here are some similarities and differences compared to [pin-project].
+
+### Similar: Safety
+
+pin-project-lite guarantees safety in much the same way as [pin-project]. Both are completely safe unless you write other unsafe code.
+
+### Different: Minimal design
+
+This library does not tackle as expansive of a range of use cases as [pin-project] does. If your use case is not already covered, please use [pin-project].
+
+### Different: No proc-macro related dependencies
+
+This is the **only** reason to use this crate. However, **if you already have proc-macro related dependencies in your crate's dependency graph, there is no benefit from using this crate.** (Note: There is almost no difference in the amount of code generated between [pin-project] and pin-project-lite.)
+
+### Different: No useful error messages
+
+This macro does not handle any invalid input. So error messages are not to be useful in most cases. If you do need useful error messages, then upon error you can pass the same input to [pin-project] to receive a helpful description of the compile error.
+
+### Different: Structs only
+
+pin-project-lite will refuse anything other than a braced struct with named fields. Enums and tuple structs are not supported.
+
+### Different: No support for custom Drop implementation
+
+pin-project supports this by [`#[pinned_drop]`][pinned-drop].
+
+### Different: No support for custom Unpin implementation
+
+pin-project supports this by [`UnsafeUnpin`][unsafe-unpin] and [`!Unpin`][not-unpin].
+
+### Different: No support for pattern matching and destructing
+
+[pin-project supports this.][naming]
+
+[`pin_project!`]: https://docs.rs/pin-project-lite/0.1/pin_project_lite/macro.pin_project.html
+[naming]: https://docs.rs/pin-project/0.4/pin_project/attr.pin_project.html
+[not-unpin]: https://docs.rs/pin-project/0.4/pin_project/attr.pin_project.html#unpin
+[pin-project]: https://github.com/taiki-e/pin-project
+[pinned-drop]: https://docs.rs/pin-project/0.4/pin_project/attr.pin_project.html#pinned_drop
+[unsafe-unpin]: https://docs.rs/pin-project/0.4/pin_project/attr.pin_project.html#unsafeunpin
+
+## License
+
+Licensed under either of
+
+* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
+* MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
diff --git a/ci/check-minimal-versions.sh b/ci/check-minimal-versions.sh
new file mode 100644
index 0000000..6152c15
--- /dev/null
+++ b/ci/check-minimal-versions.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Check all public crates with minimal version dependencies.
+#
+# Note that this script modifies Cargo.toml and Cargo.lock while this script is
+# running, and it is an error if there are any unstaged changes.
+#
+# Refs:
+# * minimal versions: https://github.com/rust-lang/cargo/issues/5657
+# * features 2.0: https://github.com/rust-lang/cargo/issues/8088
+
+set -euo pipefail
+
+# This script modifies Cargo.toml and Cargo.lock, so make sure there are no
+# unstaged changes.
+git diff --exit-code
+
+# Remove dev-dependencies from Cargo.toml to prevent the next `cargo update`
+# from determining minimal versions based on dev-dependencies.
+cargo hack --remove-dev-deps --workspace
+
+# Update Cargo.lock to minimal version dependencies.
+cargo update -Zminimal-versions
+# Run check for all public members of the workspace.
+cargo hack check --workspace --all-features --ignore-private -Zfeatures=all
+
+# Restore original Cargo.toml and Cargo.lock.
+git checkout .
diff --git a/ci/install-component.sh b/ci/install-component.sh
new file mode 100644
index 0000000..9aaa5ce
--- /dev/null
+++ b/ci/install-component.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+set -euo pipefail
+
+component="${1}"
+
+if ! rustup component add "${component}" 2>/dev/null; then
+ # If the component is unavailable on the latest nightly,
+ # use the latest toolchain with the component available.
+ # Refs: https://github.com/rust-lang/rustup-components-history#the-web-part
+ target=$(curl -sSf "https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/${component}")
+ echo "'${component}' is unavailable on the default toolchain, use the toolchain 'nightly-${target}' instead"
+
+ . ci/install-rust.sh "nightly-${target}"
+
+ rustup component add "${component}"
+fi
+
+case "${component}" in
+ rustfmt) "${component}" -V ;;
+ *) cargo "${component}" -V ;;
+esac
diff --git a/ci/install-rust.sh b/ci/install-rust.sh
new file mode 100644
index 0000000..b6625b6
--- /dev/null
+++ b/ci/install-rust.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+set -euo pipefail
+
+toolchain="${1:-nightly}"
+
+rustup set profile minimal
+rustup update "${toolchain}" --no-self-update
+rustup default "${toolchain}"
+
+rustup -V
+rustc -V
+cargo -V
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000..d51f11e
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1,25 @@
+# Rustfmt configuration
+# https://github.com/rust-lang/rustfmt/blob/master/Configurations.md
+
+# This is required for bug-fixes, which technically can't be made to the stable
+# first version.
+# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3383).
+version = "Two"
+
+# Override the default formatting style.
+# See https://internals.rust-lang.org/t/running-rustfmt-on-rust-lang-rust-and-other-rust-lang-repositories/8732/81.
+use_small_heuristics = "Max"
+# See https://github.com/rust-dev-tools/fmt-rfcs/issues/149.
+# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3370)
+overflow_delimited_expr = true
+
+# Apply rustfmt to more places.
+# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3362).
+merge_imports = true
+# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3348).
+format_code_in_doc_comments = true
+
+# Set the default settings again to always apply the proper formatting without
+# being affected by the editor settings.
+edition = "2018"
+tab_spaces = 4
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..304b0da
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,745 @@
+//! A lightweight version of [pin-project] written with declarative macros.
+//!
+//! ## Examples
+//!
+//! [`pin_project!`] macro creates a projection type covering all the fields of struct.
+//!
+//! ```rust
+//! use pin_project_lite::pin_project;
+//! use std::pin::Pin;
+//!
+//! pin_project! {
+//! struct Struct<T, U> {
+//! #[pin]
+//! pinned: T,
+//! unpinned: U,
+//! }
+//! }
+//!
+//! impl<T, U> Struct<T, U> {
+//! fn method(self: Pin<&mut Self>) {
+//! let this = self.project();
+//! let _: Pin<&mut T> = this.pinned; // Pinned reference to the field
+//! let _: &mut U = this.unpinned; // Normal reference to the field
+//! }
+//! }
+//! ```
+//!
+//! ## [pin-project] vs pin-project-lite
+//!
+//! Here are some similarities and differences compared to [pin-project].
+//!
+//! ### Similar: Safety
+//!
+//! pin-project-lite guarantees safety in much the same way as [pin-project]. Both are completely safe unless you write other unsafe code.
+//!
+//! ### Different: Minimal design
+//!
+//! This library does not tackle as expansive of a range of use cases as [pin-project] does. If your use case is not already covered, please use [pin-project].
+//!
+//! ### Different: No proc-macro related dependencies
+//!
+//! This is the **only** reason to use this crate. However, **if you already have proc-macro related dependencies in your crate's dependency graph, there is no benefit from using this crate.** (Note: There is almost no difference in the amount of code generated between [pin-project] and pin-project-lite.)
+//!
+//! ### Different: No useful error messages
+//!
+//! This macro does not handle any invalid input. So error messages are not to be useful in most cases. If you do need useful error messages, then upon error you can pass the same input to [pin-project] to receive a helpful description of the compile error.
+//!
+//! ### Different: Structs only
+//!
+//! pin-project-lite will refuse anything other than a braced struct with named fields. Enums and tuple structs are not supported.
+//!
+//! ### Different: No support for custom Drop implementation
+//!
+//! pin-project supports this by [`#[pinned_drop]`][pinned-drop].
+//!
+//! ### Different: No support for custom Unpin implementation
+//!
+//! pin-project supports this by [`UnsafeUnpin`][unsafe-unpin] and [`!Unpin`][not-unpin].
+//!
+//! ### Different: No support for pattern matching and destructing
+//!
+//! [pin-project supports this.][naming]
+//!
+//! [`pin_project!`]: https://docs.rs/pin-project-lite/0.1/pin_project_lite/macro.pin_project.html
+//! [naming]: https://docs.rs/pin-project/0.4/pin_project/attr.pin_project.html
+//! [not-unpin]: https://docs.rs/pin-project/0.4/pin_project/attr.pin_project.html#unpin
+//! [pin-project]: https://github.com/taiki-e/pin-project
+//! [pinned-drop]: https://docs.rs/pin-project/0.4/pin_project/attr.pin_project.html#pinned_drop
+//! [unsafe-unpin]: https://docs.rs/pin-project/0.4/pin_project/attr.pin_project.html#unsafeunpin
+
+#![no_std]
+#![recursion_limit = "256"]
+#![doc(html_root_url = "https://docs.rs/pin-project-lite/0.1.7")]
+#![doc(test(
+ no_crate_inject,
+ attr(deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code))
+))]
+#![warn(unsafe_code)]
+#![warn(rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
+#![warn(clippy::all, clippy::default_trait_access)]
+// mem::take and #[non_exhaustive] requires Rust 1.40
+#![allow(clippy::mem_replace_with_default, clippy::manual_non_exhaustive)]
+
+/// A macro that creates a projection type covering all the fields of struct.
+///
+/// This macro creates a projection type according to the following rules:
+///
+/// * For the field that uses `#[pin]` attribute, makes the pinned reference to the field.
+/// * For the other fields, makes the unpinned reference to the field.
+///
+/// And the following methods are implemented on the original type:
+///
+/// ```rust
+/// # use std::pin::Pin;
+/// # type Projection<'a> = &'a ();
+/// # type ProjectionRef<'a> = &'a ();
+/// # trait Dox {
+/// fn project(self: Pin<&mut Self>) -> Projection<'_>;
+/// fn project_ref(self: Pin<&Self>) -> ProjectionRef<'_>;
+/// # }
+/// ```
+///
+/// The visibility of the projected type and projection method is based on the
+/// original type. However, if the visibility of the original type is `pub`,
+/// the visibility of the projected type and the projection method is `pub(crate)`.
+///
+/// ## Safety
+///
+/// `pin_project!` macro guarantees safety in much the same way as [pin-project] crate.
+/// Both are completely safe unless you write other unsafe code.
+///
+/// See [pin-project] crate for more details.
+///
+/// ## Examples
+///
+/// ```rust
+/// use pin_project_lite::pin_project;
+/// use std::pin::Pin;
+///
+/// pin_project! {
+/// struct Struct<T, U> {
+/// #[pin]
+/// pinned: T,
+/// unpinned: U,
+/// }
+/// }
+///
+/// impl<T, U> Struct<T, U> {
+/// fn method(self: Pin<&mut Self>) {
+/// let this = self.project();
+/// let _: Pin<&mut T> = this.pinned; // Pinned reference to the field
+/// let _: &mut U = this.unpinned; // Normal reference to the field
+/// }
+/// }
+/// ```
+///
+/// If you want to call the `project()` method multiple times or later use the
+/// original [`Pin`] type, it needs to use [`.as_mut()`][`Pin::as_mut`] to avoid
+/// consuming the [`Pin`].
+///
+/// If you want to ensure that [`Unpin`] is not implemented, use `#[pin]`
+/// attribute for a [`PhantomPinned`] field.
+///
+/// ```rust
+/// use pin_project_lite::pin_project;
+/// use std::marker::PhantomPinned;
+///
+/// pin_project! {
+/// struct Struct<T> {
+/// field: T,
+/// #[pin]
+/// _pin: PhantomPinned,
+/// }
+/// }
+/// ```
+///
+/// Note that using [`PhantomPinned`] without `#[pin]` attribute has no effect.
+///
+/// [`PhantomPinned`]: core::marker::PhantomPinned
+/// [`Pin::as_mut`]: core::pin::Pin::as_mut
+/// [`Pin`]: core::pin::Pin
+/// [pin-project]: https://github.com/taiki-e/pin-project
+#[macro_export]
+macro_rules! pin_project {
+ ($($tt:tt)*) => {
+ $crate::__pin_project_internal! { $($tt)* }
+ };
+}
+
+// limitations:
+// * no support for tuple structs and enums.
+// * no support for naming the projection types.
+// * no support for multiple trait/lifetime bounds.
+// * no support for `Self` in where clauses.
+// * no support for overlapping lifetime names.
+// * no interoperability with other field attributes.
+// etc...
+
+// Not public API.
+#[doc(hidden)]
+#[macro_export]
+macro_rules! __pin_project_internal {
+ // determine_visibility
+ (
+ $(#[$attrs:meta])*
+ pub struct $ident:ident $(<
+ $( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),* $(,)?
+ $( $generics:ident
+ $(: $generics_bound:path)?
+ $(: ?$generics_unsized_bound:path)?
+ $(: $generics_lifetime_bound:lifetime)?
+ $(= $generics_default:ty)?
+ ),* $(,)?
+ >)?
+ $(where
+ $( $where_clause_ty:ty
+ $(: $where_clause_bound:path)?
+ $(: ?$where_clause_unsized_bound:path)?
+ $(: $where_clause_lifetime_bound:lifetime)?
+ ),* $(,)?
+ )?
+ {
+ $(
+ $(#[$pin:ident])?
+ $field_vis:vis $field:ident: $field_ty:ty
+ ),+ $(,)?
+ }
+ ) => {
+ $crate::__pin_project_internal! { @internal (pub(crate))
+ $(#[$attrs])*
+ pub struct $ident $(<
+ $( $lifetime $(: $lifetime_bound)? ),*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ $(= $generics_default)?
+ ),*
+ >)?
+ $(where
+ $( $where_clause_ty
+ $(: $where_clause_bound)?
+ $(: ?$where_clause_unsized_bound)?
+ $(: $where_clause_lifetime_bound)?
+ ),*
+ )?
+ {
+ $(
+ $(#[$pin])?
+ $field_vis $field: $field_ty
+ ),+
+ }
+ }
+ };
+ (
+ $(#[$attrs:meta])*
+ $vis:vis struct $ident:ident $(<
+ $( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),* $(,)?
+ $( $generics:ident
+ $(: $generics_bound:path)?
+ $(: ?$generics_unsized_bound:path)?
+ $(: $generics_lifetime_bound:lifetime)?
+ $(= $generics_default:ty)?
+ ),* $(,)?
+ >)?
+ $(where
+ $( $where_clause_ty:ty
+ $(: $where_clause_bound:path)?
+ $(: ?$where_clause_unsized_bound:path)?
+ $(: $where_clause_lifetime_bound:lifetime)?
+ ),* $(,)?
+ )?
+ {
+ $(
+ $(#[$pin:ident])?
+ $field_vis:vis $field:ident: $field_ty:ty
+ ),+ $(,)?
+ }
+ ) => {
+ $crate::__pin_project_internal! { @internal ($vis)
+ $(#[$attrs])*
+ $vis struct $ident $(<
+ $( $lifetime $(: $lifetime_bound)? ),*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ $(= $generics_default)?
+ ),*
+ >)?
+ $(where
+ $( $where_clause_ty
+ $(: $where_clause_bound)?
+ $(: ?$where_clause_unsized_bound)?
+ $(: $where_clause_lifetime_bound)?
+ ),*
+ )?
+ {
+ $(
+ $(#[$pin])?
+ $field_vis $field: $field_ty
+ ),+
+ }
+ }
+ };
+
+ (@internal ($proj_vis:vis)
+ $(#[$attrs:meta])*
+ $vis:vis struct $ident:ident $(<
+ $( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),*
+ $( $generics:ident
+ $(: $generics_bound:path)?
+ $(: ?$generics_unsized_bound:path)?
+ $(: $generics_lifetime_bound:lifetime)?
+ $(= $generics_default:ty)?
+ ),*
+ >)?
+ $(where
+ $( $where_clause_ty:ty
+ $(: $where_clause_bound:path)?
+ $(: ?$where_clause_unsized_bound:path)?
+ $(: $where_clause_lifetime_bound:lifetime)?
+ ),*
+ )?
+ {
+ $(
+ $(#[$pin:ident])?
+ $field_vis:vis $field:ident: $field_ty:ty
+ ),+
+ }
+ ) => {
+ $(#[$attrs])*
+ $vis struct $ident $(<
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ $(= $generics_default)?
+ ),*
+ >)?
+ $(where
+ $( $where_clause_ty
+ $(: $where_clause_bound)?
+ $(: ?$where_clause_unsized_bound)?
+ $(: $where_clause_lifetime_bound)?
+ ),*
+ )?
+ {
+ $(
+ $field_vis $field: $field_ty
+ ),+
+ }
+
+ #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
+ #[allow(clippy::used_underscore_binding)]
+ const _: () = {
+ $crate::__pin_project_internal! { @make_proj_ty ($proj_vis)
+ $vis struct $ident $(<
+ $( $lifetime $(: $lifetime_bound)? ),*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ $(= $generics_default)?
+ ),*
+ >)?
+ $(where
+ $( $where_clause_ty
+ $(: $where_clause_bound)?
+ $(: ?$where_clause_unsized_bound)?
+ $(: $where_clause_lifetime_bound)?
+ ),*
+ )?
+ {
+ $(
+ $(#[$pin])?
+ $field_vis $field: $field_ty
+ ),+
+ }
+ }
+
+ impl $(<
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ ),*
+ >)?
+ $ident $(< $($lifetime,)* $($generics),* >)?
+ $(where
+ $( $where_clause_ty
+ $(: $where_clause_bound)?
+ $(: ?$where_clause_unsized_bound)?
+ $(: $where_clause_lifetime_bound)?
+ ),*
+ )?
+ {
+ $proj_vis fn project<'__pin>(
+ self: $crate::__private::Pin<&'__pin mut Self>,
+ ) -> Projection<'__pin $(, $($lifetime,)* $($generics),* )?> {
+ unsafe {
+ let this = self.get_unchecked_mut();
+ Projection {
+ $(
+ $field: $crate::__pin_project_internal!(@make_unsafe_field_proj
+ this; $(#[$pin])? $field; mut
+ )
+ ),+
+ }
+ }
+ }
+ $proj_vis fn project_ref<'__pin>(
+ self: $crate::__private::Pin<&'__pin Self>,
+ ) -> ProjectionRef<'__pin $(, $($lifetime,)* $($generics),* )?> {
+ unsafe {
+ let this = self.get_ref();
+ ProjectionRef {
+ $(
+ $field: $crate::__pin_project_internal!(@make_unsafe_field_proj
+ this; $(#[$pin])? $field;
+ )
+ ),+
+ }
+ }
+ }
+ }
+
+ // Automatically create the appropriate conditional `Unpin` implementation.
+ //
+ // Basically this is equivalent to the following code:
+ // ```rust
+ // impl<T, U> Unpin for Struct<T, U> where T: Unpin {}
+ // ```
+ //
+ // However, if struct is public and there is a private type field,
+ // this would cause an E0446 (private type in public interface).
+ //
+ // When RFC 2145 is implemented (rust-lang/rust#48054),
+ // this will become a lint, rather then a hard error.
+ //
+ // As a workaround for this, we generate a new struct, containing all of the pinned
+ // fields from our #[pin_project] type. This struct is delcared within
+ // a function, which makes it impossible to be named by user code.
+ // This guarnatees that it will use the default auto-trait impl for Unpin -
+ // that is, it will implement Unpin iff all of its fields implement Unpin.
+ // This type can be safely declared as 'public', satisfiying the privacy
+ // checker without actually allowing user code to access it.
+ //
+ // This allows users to apply the #[pin_project] attribute to types
+ // regardless of the privacy of the types of their fields.
+ //
+ // See also https://github.com/taiki-e/pin-project/pull/53.
+ $vis struct __Origin <'__pin $(,
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ ),*
+ )?>
+ $(where
+ $( $where_clause_ty
+ $(: $where_clause_bound)?
+ $(: ?$where_clause_unsized_bound)?
+ $(: $where_clause_lifetime_bound)?
+ ),*
+ )?
+ {
+ __dummy_lifetime: $crate::__private::PhantomData<&'__pin ()>,
+ $(
+ $field: $crate::__pin_project_internal!(@make_unpin_bound
+ $(#[$pin])? $field_ty
+ )
+ ),+
+ }
+ impl <'__pin $(,
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ ),*
+ )?>
+ $crate::__private::Unpin for $ident $(< $($lifetime,)* $($generics),* >)?
+ where
+ __Origin <'__pin $(, $($lifetime,)* $($generics),* )?>: $crate::__private::Unpin
+ $(,
+ $( $where_clause_ty
+ $(: $where_clause_bound)?
+ $(: ?$where_clause_unsized_bound)?
+ $(: $where_clause_lifetime_bound)?
+ ),*
+ )?
+ {
+ }
+
+ // Ensure that struct does not implement `Drop`.
+ //
+ // There are two possible cases:
+ // 1. The user type does not implement Drop. In this case,
+ // the first blanked impl will not apply to it. This code
+ // will compile, as there is only one impl of MustNotImplDrop for the user type
+ // 2. The user type does impl Drop. This will make the blanket impl applicable,
+ // which will then comflict with the explicit MustNotImplDrop impl below.
+ // This will result in a compilation error, which is exactly what we want.
+ trait MustNotImplDrop {}
+ #[allow(clippy::drop_bounds)]
+ impl<T: $crate::__private::Drop> MustNotImplDrop for T {}
+ impl $(<
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ ),*
+ >)?
+ MustNotImplDrop for $ident $(< $($lifetime,)* $($generics),* >)?
+ $(where
+ $( $where_clause_ty
+ $(: $where_clause_bound)?
+ $(: ?$where_clause_unsized_bound)?
+ $(: $where_clause_lifetime_bound)?
+ ),*
+ )?
+ {
+ }
+
+ // Ensure that it's impossible to use pin projections on a #[repr(packed)] struct.
+ //
+ // Taking a reference to a packed field is unsafe, amd appplying
+ // #[deny(safe_packed_borrows)] makes sure that doing this without
+ // an 'unsafe' block (which we deliberately do not generate)
+ // is a hard error.
+ //
+ // If the struct ends up having #[repr(packed)] applied somehow,
+ // this will generate an (unfriendly) error message. Under all reasonable
+ // circumstances, we'll detect the #[repr(packed)] attribute, and generate
+ // a much nicer error above.
+ //
+ // See https://github.com/taiki-e/pin-project/pull/34 for more details.
+ #[deny(safe_packed_borrows)]
+ fn __assert_not_repr_packed $(<
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ ),*
+ >)?
+ (
+ this: &$ident $(< $($lifetime,)* $($generics),* >)?
+ )
+ $(where
+ $( $where_clause_ty
+ $(: $where_clause_bound)?
+ $(: ?$where_clause_unsized_bound)?
+ $(: $where_clause_lifetime_bound)?
+ ),*
+ )?
+ {
+ $(
+ &this.$field;
+ )+
+ }
+ };
+ };
+
+ // make_proj_ty
+ (@make_proj_ty ($proj_vis:vis)
+ $vis:vis struct $ident:ident $(<
+ $( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),*
+ $( $generics:ident
+ $(: $generics_bound:path)?
+ $(: ?$generics_unsized_bound:path)?
+ $(: $generics_lifetime_bound:lifetime)?
+ $(= $generics_default:ty)?
+ ),*
+ >)?
+ where
+ $( $where_clause_ty:ty
+ $(: $where_clause_bound:path)?
+ $(: ?$where_clause_unsized_bound:path)?
+ $(: $where_clause_lifetime_bound:lifetime)?
+ ),*
+ {
+ $(
+ $(#[$pin:ident])?
+ $field_vis:vis $field:ident: $field_ty:ty
+ ),+
+ }
+ ) => {
+ #[allow(dead_code)] // This lint warns unused fields/variants.
+ #[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
+ #[allow(clippy::type_repetition_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/4326
+ $proj_vis struct Projection <'__pin $(,
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ ),*
+ )?>
+ where
+ $ident $(< $($lifetime,)* $($generics),* >)?: '__pin,
+ $( $where_clause_ty
+ $(: $where_clause_bound)?
+ $(: ?$where_clause_unsized_bound)?
+ $(: $where_clause_lifetime_bound)?
+ ),*
+ {
+ $(
+ $field_vis $field: $crate::__pin_project_internal!(@make_proj_field
+ $(#[$pin])? $field_ty; mut
+ )
+ ),+
+ }
+ #[allow(dead_code)] // This lint warns unused fields/variants.
+ #[allow(clippy::type_repetition_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/4326
+ $proj_vis struct ProjectionRef <'__pin $(,
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ ),*
+ )?>
+ where
+ $ident $(< $($lifetime,)* $($generics),* >)?: '__pin,
+ $( $where_clause_ty
+ $(: $where_clause_bound)?
+ $(: ?$where_clause_unsized_bound)?
+ $(: $where_clause_lifetime_bound)?
+ ),*
+ {
+ $(
+ $field_vis $field: $crate::__pin_project_internal!(@make_proj_field
+ $(#[$pin])? $field_ty;
+ )
+ ),+
+ }
+ };
+ (@make_proj_ty ($proj_vis:vis)
+ $vis:vis struct $ident:ident $(<
+ $( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),*
+ $( $generics:ident
+ $(: $generics_bound:path)?
+ $(: ?$generics_unsized_bound:path)?
+ $(: $generics_lifetime_bound:lifetime)?
+ $(= $generics_default:ty)?
+ ),*
+ >)?
+ {
+ $(
+ $(#[$pin:ident])?
+ $field_vis:vis $field:ident: $field_ty:ty
+ ),+
+ }
+ ) => {
+ #[allow(dead_code)] // This lint warns unused fields/variants.
+ #[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
+ #[allow(clippy::type_repetition_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/4326
+ $proj_vis struct Projection <'__pin $(,
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ ),*
+ )?>
+ where
+ $ident $(< $($lifetime,)* $($generics),* >)?: '__pin,
+ {
+ $(
+ $field_vis $field: $crate::__pin_project_internal!(@make_proj_field
+ $(#[$pin])? $field_ty; mut
+ )
+ ),+
+ }
+ #[allow(dead_code)] // This lint warns unused fields/variants.
+ #[allow(clippy::type_repetition_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/4326
+ $proj_vis struct ProjectionRef <'__pin $(,
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ ),*
+ )?>
+ where
+ $ident $(< $($lifetime,)* $($generics),* >)?: '__pin,
+ {
+ $(
+ $field_vis $field: $crate::__pin_project_internal!(@make_proj_field
+ $(#[$pin])? $field_ty;
+ )
+ ),+
+ }
+ };
+
+ // make_unpin_bound
+ (@make_unpin_bound
+ #[pin]
+ $field_ty:ty
+ ) => {
+ $field_ty
+ };
+ (@make_unpin_bound
+ $field_ty:ty
+ ) => {
+ $crate::__private::AlwaysUnpin<$field_ty>
+ };
+
+ // make_unsafe_field_proj
+ (@make_unsafe_field_proj
+ $this:ident;
+ #[pin]
+ $field:ident;
+ $($mut:ident)?
+ ) => {
+ $crate::__private::Pin::new_unchecked(&$($mut)? $this.$field)
+ };
+ (@make_unsafe_field_proj
+ $this:ident;
+ $field:ident;
+ $($mut:ident)?
+ ) => {
+ &$($mut)? $this.$field
+ };
+
+ // make_proj_field
+ (@make_proj_field
+ #[pin]
+ $field_ty:ty;
+ $($mut:ident)?
+ ) => {
+ $crate::__private::Pin<&'__pin $($mut)? ($field_ty)>
+ };
+ (@make_proj_field
+ $field_ty:ty;
+ $($mut:ident)?
+ ) => {
+ &'__pin $($mut)? ($field_ty)
+ };
+
+ // limitation: no useful error messages (wontfix)
+}
+
+// Not public API.
+#[doc(hidden)]
+pub mod __private {
+ #[doc(hidden)]
+ pub use core::{
+ marker::{PhantomData, Unpin},
+ ops::Drop,
+ pin::Pin,
+ };
+
+ // This is an internal helper struct used by `pin_project!`.
+ #[doc(hidden)]
+ pub struct AlwaysUnpin<T: ?Sized>(PhantomData<T>);
+
+ impl<T: ?Sized> Unpin for AlwaysUnpin<T> {}
+}
diff --git a/tests/compiletest.rs b/tests/compiletest.rs
new file mode 100644
index 0000000..d181491
--- /dev/null
+++ b/tests/compiletest.rs
@@ -0,0 +1,8 @@
+#![warn(rust_2018_idioms, single_use_lifetimes)]
+
+#[rustversion::attr(not(nightly), ignore)]
+#[test]
+fn ui() {
+ let t = trybuild::TestCases::new();
+ t.compile_fail("tests/ui/*.rs");
+}
diff --git a/tests/include/basic.rs b/tests/include/basic.rs
new file mode 100644
index 0000000..967cf81
--- /dev/null
+++ b/tests/include/basic.rs
@@ -0,0 +1,10 @@
+// default pin_project! is completely safe.
+
+::pin_project_lite::pin_project! {
+ #[derive(Debug)]
+ pub struct DefaultStruct<T, U> {
+ #[pin]
+ pub pinned: T,
+ pub unpinned: U,
+ }
+}
diff --git a/tests/lint.rs b/tests/lint.rs
new file mode 100644
index 0000000..24491bb
--- /dev/null
+++ b/tests/lint.rs
@@ -0,0 +1,90 @@
+#![warn(rust_2018_idioms, single_use_lifetimes)]
+#![warn(future_incompatible, nonstandard_style, rust_2018_compatibility, unused)]
+#![warn(clippy::all, clippy::pedantic, clippy::nursery)]
+#![forbid(unsafe_code)]
+
+#[allow(unknown_lints)] // for old compilers
+#[warn(
+ absolute_paths_not_starting_with_crate,
+ anonymous_parameters,
+ box_pointers,
+ confusable_idents,
+ deprecated_in_future,
+ elided_lifetimes_in_paths,
+ explicit_outlives_requirements,
+ indirect_structural_match,
+ keyword_idents,
+ macro_use_extern_crate,
+ meta_variable_misuse,
+ missing_copy_implementations,
+ missing_crate_level_docs,
+ missing_debug_implementations,
+ missing_docs,
+ missing_doc_code_examples,
+ non_ascii_idents,
+ private_doc_tests,
+ single_use_lifetimes,
+ trivial_casts,
+ trivial_numeric_casts,
+ unaligned_references,
+ unreachable_pub,
+ unstable_features,
+ unused_extern_crates,
+ unused_import_braces,
+ unused_lifetimes,
+ unused_qualifications,
+ unused_results,
+ variant_size_differences
+)]
+// unused_crate_dependencies: unrelated
+// unsafe_code: checked in forbid_unsafe module
+// unsafe_block_in_unsafe_fn: unstable
+pub mod basic {
+ include!("include/basic.rs");
+}
+
+pub mod clippy {
+ use pin_project_lite::pin_project;
+
+ pin_project! {
+ pub struct MutMut<'a, T, U> {
+ #[pin]
+ pub pinned: &'a mut T,
+ pub unpinned: &'a mut U,
+ }
+ }
+
+ pin_project! {
+ pub struct TypeRepetitionInBoundsStruct<T, U>
+ where
+ TypeRepetitionInBoundsStruct<T, U>: Sized,
+ {
+ #[pin]
+ pub pinned: T,
+ pub unpinned: U,
+ }
+ }
+
+ pin_project! {
+ pub struct UsedUnderscoreBindingStruct<T, U> {
+ #[pin]
+ pub _pinned: T,
+ pub _unpinned: U,
+ }
+ }
+}
+
+#[rustversion::attr(not(nightly), ignore)]
+#[test]
+fn check_lint_list() {
+ use std::{env, process::Command};
+
+ (|| -> Result<(), Box<dyn std::error::Error>> {
+ let current = include_str!("lint.txt");
+ let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
+ let new = String::from_utf8(Command::new(rustc).args(&["-W", "help"]).output()?.stdout)?;
+ assert_eq!(current, &new);
+ Ok(())
+ })()
+ .unwrap_or_else(|e| panic!("{}", e));
+}
diff --git a/tests/lint.txt b/tests/lint.txt
new file mode 100644
index 0000000..8de71e0
--- /dev/null
+++ b/tests/lint.txt
@@ -0,0 +1,138 @@
+
+Available lint options:
+ -W <foo> Warn about <foo>
+ -A <foo> Allow <foo>
+ -D <foo> Deny <foo>
+ -F <foo> Forbid <foo> (deny <foo> and all attempts to override)
+
+
+Lint checks provided by rustc:
+
+ name default meaning
+ ---- ------- -------
+ absolute-paths-not-starting-with-crate allow fully qualified paths that start with a module name instead of `crate`, `self`, or an extern crate name
+ anonymous-parameters allow detects anonymous parameters
+ box-pointers allow use of owned (Box type) heap memory
+ confusable-idents allow detects visually confusable pairs between identifiers
+ deprecated-in-future allow detects use of items that will be deprecated in a future version
+ elided-lifetimes-in-paths allow hidden lifetime parameters in types are deprecated
+ explicit-outlives-requirements allow outlives requirements can be inferred
+ indirect-structural-match allow pattern with const indirectly referencing non-structural-match type
+ keyword-idents allow detects edition keywords being used as an identifier
+ macro-use-extern-crate allow the `#[macro_use]` attribute is now deprecated in favor of using macros via the module system
+ meta-variable-misuse allow possible meta-variable misuse at macro definition
+ missing-copy-implementations allow detects potentially-forgotten implementations of `Copy`
+ missing-crate-level-docs allow detects crates with no crate-level documentation
+ missing-debug-implementations allow detects missing implementations of Debug
+ missing-docs allow detects missing documentation for public members
+ missing-doc-code-examples allow detects publicly-exported items without code samples in their documentation
+ non-ascii-idents allow detects non-ASCII identifiers
+ private-doc-tests allow detects code samples in docs of private items not documented by rustdoc
+ single-use-lifetimes allow detects lifetime parameters that are only used once
+ trivial-casts allow detects trivial casts which could be removed
+ trivial-numeric-casts allow detects trivial casts of numeric types which could be removed
+ unaligned-references allow detects unaligned references to fields of packed structs
+ unreachable-pub allow `pub` items not reachable from crate root
+ unsafe-code allow usage of `unsafe` code
+ unsafe-op-in-unsafe-fn allow unsafe operations in unsafe functions without an explicit unsafe block are deprecated
+ unstable-features allow enabling unstable features (deprecated. do not use)
+ unused-crate-dependencies allow crate dependencies that are never used
+ unused-extern-crates allow extern crates that are never used
+ unused-import-braces allow unnecessary braces around an imported item
+ unused-lifetimes allow detects lifetime parameters that are never used
+ unused-qualifications allow detects unnecessarily qualified names
+ unused-results allow unused result of an expression in a statement
+ variant-size-differences allow detects enums with widely varying variant sizes
+ array-into-iter warn detects calling `into_iter` on arrays
+ asm-sub-register warn using only a subset of a register for inline asm inputs
+ bare-trait-objects warn suggest using `dyn Trait` for trait objects
+ bindings-with-variant-name warn detects pattern bindings with the same name as one of the matched variants
+ coherence-leak-check warn distinct impls distinguished only by the leak-check code
+ dead-code warn detect unused, unexported items
+ deprecated warn detects use of deprecated items
+ ellipsis-inclusive-range-patterns warn `...` range patterns are deprecated
+ exported-private-dependencies warn public interface leaks type from a private dependency
+ illegal-floating-point-literal-pattern warn floating-point literals cannot be used in patterns
+ improper-ctypes warn proper use of libc types in foreign modules
+ incomplete-features warn incomplete features that may function improperly in some or all cases
+ inline-no-sanitize warn detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]`
+ intra-doc-link-resolution-failure warn failures in resolving intra-doc link targets
+ invalid-codeblock-attribute warn codeblock attribute looks a lot like a known one
+ invalid-value warn an invalid value is being created (such as a NULL reference)
+ irrefutable-let-patterns warn detects irrefutable patterns in if-let and while-let statements
+ late-bound-lifetime-arguments warn detects generic lifetime arguments in path segments with late bound lifetime parameters
+ mutable-borrow-reservation-conflict warn reservation of a two-phased borrow conflicts with other shared borrows
+ non-camel-case-types warn types, variants, traits and type parameters should have camel case names
+ non-shorthand-field-patterns warn using `Struct { x: x }` instead of `Struct { x }` in a pattern
+ non-snake-case warn variables, methods, functions, lifetime parameters and modules should have snake case names
+ non-upper-case-globals warn static constants should have uppercase identifiers
+ no-mangle-generic-items warn generic items must be mangled
+ overlapping-patterns warn detects overlapping patterns
+ path-statements warn path statements with no effect
+ private-in-public warn detect private items in public interfaces not caught by the old implementation
+ proc-macro-derive-resolution-fallback warn detects proc macro derives using inaccessible names from parent modules
+ redundant-semicolons warn detects unnecessary trailing semicolons
+ renamed-and-removed-lints warn lints that have been renamed or removed
+ safe-packed-borrows warn safe borrows of fields of packed structs were erroneously allowed
+ stable-features warn stable features found in `#[feature]` directive
+ trivial-bounds warn these bounds don't depend on an type parameters
+ type-alias-bounds warn bounds in type aliases are not enforced
+ tyvar-behind-raw-pointer warn raw pointer to an inference variable
+ uncommon-codepoints warn detects uncommon Unicode codepoints in identifiers
+ unconditional-recursion warn functions that cannot return without calling themselves
+ unknown-lints warn unrecognized lint attribute
+ unnameable-test-items warn detects an item that cannot be named being marked as `#[test_case]`
+ unreachable-code warn detects unreachable code paths
+ unreachable-patterns warn detects unreachable patterns
+ unstable-name-collisions warn detects name collision with an existing but unstable method
+ unused-allocation warn detects unnecessary allocations that can be eliminated
+ unused-assignments warn detect assignments that will never be read
+ unused-attributes warn detects attributes that were not used by the compiler
+ unused-braces warn unnecessary braces around an expression
+ unused-comparisons warn comparisons made useless by limits of the types involved
+ unused-doc-comments warn detects doc comments that aren't used by rustdoc
+ unused-features warn unused features found in crate-level `#[feature]` directives
+ unused-imports warn imports that are never used
+ unused-labels warn detects labels that are never used
+ unused-macros warn detects macros that were not used
+ unused-must-use warn unused result of a type flagged as `#[must_use]`
+ unused-mut warn detect mut variables which don't need to be mutable
+ unused-parens warn `if`, `match`, `while` and `return` do not need parentheses
+ unused-unsafe warn unnecessary use of an `unsafe` block
+ unused-variables warn detect variables which are not used in any way
+ warnings warn mass-change the level for lints which produce warnings
+ where-clauses-object-safety warn checks the object safety of where clauses
+ while-true warn suggest using `loop { }` instead of `while true { }`
+ ambiguous-associated-items deny ambiguous associated items
+ arithmetic-overflow deny arithmetic operation overflows
+ conflicting-repr-hints deny conflicts between `#[repr(..)]` hints that were previously accepted and used in practice
+ const-err deny constant evaluation detected erroneous expression
+ ill-formed-attribute-input deny ill-formed attribute inputs that were previously accepted and used in practice
+ invalid-type-param-default deny type parameter default erroneously allowed in invalid location
+ macro-expanded-macro-exports-accessed-by-absolute-paths deny macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
+ missing-fragment-specifier deny detects missing fragment specifiers in unused `macro_rules!` patterns
+ mutable-transmutes deny mutating transmuted &mut T from &T may cause undefined behavior
+ no-mangle-const-items deny const items will not have their symbols exported
+ order-dependent-trait-objects deny trait-object types were treated as different depending on marker-trait order
+ overflowing-literals deny literal out of range for its type
+ patterns-in-fns-without-body deny patterns in functions without body were erroneously allowed
+ pub-use-of-private-extern-crate deny detect public re-exports of private extern crates
+ soft-unstable deny a feature gate that doesn't break dependent crates
+ unconditional-panic deny operation will cause a panic at runtime
+ unknown-crate-types deny unknown crate type found in `#[crate_type]` directive
+
+
+Lint groups provided by rustc:
+
+ name sub-lints
+ ---- ---------
+ warnings all lints that are set to issue warnings
+ future-incompatible keyword-idents, anonymous-parameters, illegal-floating-point-literal-pattern, private-in-public, pub-use-of-private-extern-crate, invalid-type-param-default, safe-packed-borrows, patterns-in-fns-without-body, missing-fragment-specifier, late-bound-lifetime-arguments, order-dependent-trait-objects, coherence-leak-check, tyvar-behind-raw-pointer, absolute-paths-not-starting-with-crate, unstable-name-collisions, where-clauses-object-safety, proc-macro-derive-resolution-fallback, macro-expanded-macro-exports-accessed-by-absolute-paths, ill-formed-attribute-input, conflicting-repr-hints, ambiguous-associated-items, mutable-borrow-reservation-conflict, indirect-structural-match, soft-unstable, array-into-iter
+ nonstandard-style non-camel-case-types, non-snake-case, non-upper-case-globals
+ rust-2018-compatibility keyword-idents, anonymous-parameters, tyvar-behind-raw-pointer, absolute-paths-not-starting-with-crate
+ rust-2018-idioms bare-trait-objects, unused-extern-crates, ellipsis-inclusive-range-patterns, elided-lifetimes-in-paths, explicit-outlives-requirements
+ rustdoc intra-doc-link-resolution-failure, invalid-codeblock-attribute, missing-doc-code-examples, private-doc-tests
+ unused unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, overlapping-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons
+
+
+Compiler plugins can provide additional lints and lint groups. To see a listing of these, re-run `rustc -W help` with a crate filename.
diff --git a/tests/test.rs b/tests/test.rs
new file mode 100644
index 0000000..06ec259
--- /dev/null
+++ b/tests/test.rs
@@ -0,0 +1,384 @@
+#![no_std]
+#![warn(rust_2018_idioms, single_use_lifetimes)]
+#![allow(dead_code)]
+
+use core::{marker::PhantomPinned, pin::Pin};
+use pin_project_lite::pin_project;
+
+#[test]
+fn projection() {
+ pin_project! {
+ struct Struct<T, U> {
+ #[pin]
+ field1: T,
+ field2: U,
+ }
+ }
+
+ let mut s = Struct { field1: 1, field2: 2 };
+ let mut s_orig = Pin::new(&mut s);
+ let s = s_orig.as_mut().project();
+
+ let x: Pin<&mut i32> = s.field1;
+ assert_eq!(*x, 1);
+
+ let y: &mut i32 = s.field2;
+ assert_eq!(*y, 2);
+
+ assert_eq!(s_orig.as_ref().field1, 1);
+ assert_eq!(s_orig.as_ref().field2, 2);
+
+ let mut s = Struct { field1: 1, field2: 2 };
+
+ let s = Pin::new(&mut s).project();
+
+ let _: Pin<&mut i32> = s.field1;
+ let _: &mut i32 = s.field2;
+}
+
+#[test]
+fn where_clause() {
+ pin_project! {
+ struct Struct<T>
+ where
+ T: Copy,
+ {
+ field: T,
+ }
+ }
+}
+
+#[test]
+fn where_clause_and_associated_type_field() {
+ pin_project! {
+ struct Struct1<I>
+ where
+ I: Iterator,
+ {
+ #[pin]
+ field1: I,
+ field2: I::Item,
+ }
+ }
+
+ pin_project! {
+ struct Struct2<I, J>
+ where
+ I: Iterator<Item = J>,
+ {
+ #[pin]
+ field1: I,
+ field2: J,
+ }
+ }
+
+ pin_project! {
+ pub struct Struct3<T>
+ where
+ T: 'static,
+ {
+ field: T,
+ }
+ }
+
+ trait Static: 'static {}
+
+ impl<T> Static for Struct3<T> {}
+}
+
+#[test]
+fn derive_copy() {
+ pin_project! {
+ #[derive(Clone, Copy)]
+ struct Struct<T> {
+ val: T,
+ }
+ }
+
+ fn is_copy<T: Copy>() {}
+
+ is_copy::<Struct<u8>>();
+}
+
+#[test]
+fn move_out() {
+ struct NotCopy;
+
+ pin_project! {
+ struct Struct {
+ val: NotCopy,
+ }
+ }
+
+ let x = Struct { val: NotCopy };
+ let _val: NotCopy = x.val;
+}
+
+#[test]
+fn trait_bounds_on_type_generics() {
+ pin_project! {
+ pub struct Struct1<'a, T: ?Sized> {
+ field: &'a mut T,
+ }
+ }
+
+ pin_project! {
+ pub struct Struct2<'a, T: ::core::fmt::Debug> {
+ field: &'a mut T,
+ }
+ }
+
+ pin_project! {
+ pub struct Struct3<'a, T: core::fmt::Debug> {
+ field: &'a mut T,
+ }
+ }
+
+ // pin_project! {
+ // pub struct Struct4<'a, T: core::fmt::Debug + core::fmt::Display> {
+ // field: &'a mut T,
+ // }
+ // }
+
+ // pin_project! {
+ // pub struct Struct5<'a, T: core::fmt::Debug + ?Sized> {
+ // field: &'a mut T,
+ // }
+ // }
+
+ pin_project! {
+ pub struct Struct6<'a, T: core::fmt::Debug = [u8; 16]> {
+ field: &'a mut T,
+ }
+ }
+
+ let _: Struct6<'_> = Struct6 { field: &mut [0u8; 16] };
+
+ pin_project! {
+ pub struct Struct7<T: 'static> {
+ field: T,
+ }
+ }
+
+ trait Static: 'static {}
+
+ impl<T> Static for Struct7<T> {}
+
+ pin_project! {
+ pub struct Struct8<'a, 'b: 'a> {
+ field1: &'a u8,
+ field2: &'b u8,
+ }
+ }
+}
+
+#[test]
+fn private_type_in_public_type() {
+ pin_project! {
+ pub struct PublicStruct<T> {
+ #[pin]
+ inner: PrivateStruct<T>,
+ }
+ }
+
+ struct PrivateStruct<T>(T);
+}
+
+#[test]
+fn lifetime_project() {
+ pin_project! {
+ struct Struct1<T, U> {
+ #[pin]
+ pinned: T,
+ unpinned: U,
+ }
+ }
+
+ pin_project! {
+ struct Struct2<'a, T, U> {
+ #[pin]
+ pinned: &'a mut T,
+ unpinned: U,
+ }
+ }
+
+ impl<T, U> Struct1<T, U> {
+ fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a T> {
+ self.project_ref().pinned
+ }
+ fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut T> {
+ self.project().pinned
+ }
+ }
+
+ impl<'b, T, U> Struct2<'b, T, U> {
+ fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a &'b mut T> {
+ self.project_ref().pinned
+ }
+ fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut &'b mut T> {
+ self.project().pinned
+ }
+ }
+}
+
+#[test]
+fn lifetime_project_elided() {
+ pin_project! {
+ struct Struct1<T, U> {
+ #[pin]
+ pinned: T,
+ unpinned: U,
+ }
+ }
+
+ pin_project! {
+ struct Struct2<'a, T, U> {
+ #[pin]
+ pinned: &'a mut T,
+ unpinned: U,
+ }
+ }
+
+ impl<T, U> Struct1<T, U> {
+ fn get_pin_ref(self: Pin<&Self>) -> Pin<&T> {
+ self.project_ref().pinned
+ }
+ fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
+ self.project().pinned
+ }
+ }
+
+ impl<'b, T, U> Struct2<'b, T, U> {
+ fn get_pin_ref(self: Pin<&Self>) -> Pin<&&'b mut T> {
+ self.project_ref().pinned
+ }
+ fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut &'b mut T> {
+ self.project().pinned
+ }
+ }
+}
+
+mod visibility {
+ use pin_project_lite::pin_project;
+
+ pin_project! {
+ pub(crate) struct A {
+ pub b: u8,
+ }
+ }
+}
+
+#[test]
+fn visibility() {
+ let mut x = visibility::A { b: 0 };
+ let x = Pin::new(&mut x);
+ let y = x.as_ref().project_ref();
+ let _: &u8 = y.b;
+ let y = x.project();
+ let _: &mut u8 = y.b;
+}
+
+#[test]
+fn trivial_bounds() {
+ pin_project! {
+ pub struct NoGenerics {
+ #[pin]
+ field: PhantomPinned,
+ }
+ }
+}
+
+#[test]
+fn dst() {
+ pin_project! {
+ pub struct Struct1<T: ?Sized> {
+ x: T,
+ }
+ }
+
+ let mut x = Struct1 { x: 0_u8 };
+ let x: Pin<&mut Struct1<dyn core::fmt::Debug>> = Pin::new(&mut x as _);
+ let _y: &mut (dyn core::fmt::Debug) = x.project().x;
+
+ pin_project! {
+ pub struct Struct2<T: ?Sized> {
+ #[pin]
+ x: T,
+ }
+ }
+
+ let mut x = Struct2 { x: 0_u8 };
+ let x: Pin<&mut Struct2<dyn core::fmt::Debug + Unpin>> = Pin::new(&mut x as _);
+ let _y: Pin<&mut (dyn core::fmt::Debug + Unpin)> = x.project().x;
+}
+
+#[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993
+#[test]
+fn unsized_in_where_clause() {
+ pin_project! {
+ struct Struct3<T>
+ where
+ T: ?Sized,
+ {
+ x: T,
+ }
+ }
+
+ pin_project! {
+ struct Struct4<T>
+ where
+ T: ?Sized,
+ {
+ #[pin]
+ x: T,
+ }
+ }
+}
+
+#[test]
+fn dyn_type() {
+ pin_project! {
+ struct Struct1 {
+ f: dyn core::fmt::Debug,
+ }
+ }
+
+ pin_project! {
+ struct Struct2 {
+ #[pin]
+ f: dyn core::fmt::Debug,
+ }
+ }
+
+ pin_project! {
+ struct Struct3 {
+ f: dyn core::fmt::Debug + Send,
+ }
+ }
+
+ pin_project! {
+ struct Struct4 {
+ #[pin]
+ f: dyn core::fmt::Debug + Send,
+ }
+ }
+}
+
+#[test]
+fn no_infer_outlives() {
+ trait Bar<X> {
+ type Y;
+ }
+
+ struct Example<A>(A);
+
+ impl<X, T> Bar<X> for Example<T> {
+ type Y = Option<T>;
+ }
+
+ pin_project! {
+ struct Foo<A, B> {
+ _x: <Example<A> as Bar<B>>::Y,
+ }
+ }
+}
diff --git a/tests/ui/conflict-drop.rs b/tests/ui/conflict-drop.rs
new file mode 100644
index 0000000..870059d
--- /dev/null
+++ b/tests/ui/conflict-drop.rs
@@ -0,0 +1,15 @@
+use pin_project_lite::pin_project;
+
+pin_project! { //~ ERROR E0119
+ struct Foo<T, U> {
+ #[pin]
+ future: T,
+ field: U,
+ }
+}
+
+impl<T, U> Drop for Foo<T, U> {
+ fn drop(&mut self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/conflict-drop.stderr b/tests/ui/conflict-drop.stderr
new file mode 100644
index 0000000..f97c92b
--- /dev/null
+++ b/tests/ui/conflict-drop.stderr
@@ -0,0 +1,16 @@
+error[E0119]: conflicting implementations of trait `_::MustNotImplDrop` for type `Foo<_, _>`:
+ --> $DIR/conflict-drop.rs:3:1
+ |
+3 | / pin_project! { //~ ERROR E0119
+4 | | struct Foo<T, U> {
+5 | | #[pin]
+6 | | future: T,
+7 | | field: U,
+8 | | }
+9 | | }
+ | | ^
+ | | |
+ | |_first implementation here
+ | conflicting implementation for `Foo<_, _>`
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/conflict-unpin.rs b/tests/ui/conflict-unpin.rs
new file mode 100644
index 0000000..f702f06
--- /dev/null
+++ b/tests/ui/conflict-unpin.rs
@@ -0,0 +1,40 @@
+use pin_project_lite::pin_project;
+
+// The same implementation.
+
+pin_project! { //~ ERROR E0119
+ struct Foo<T, U> {
+ #[pin]
+ future: T,
+ field: U,
+ }
+}
+
+// conflicting implementations
+impl<T, U> Unpin for Foo<T, U> where T: Unpin {} // Conditional Unpin impl
+
+// The implementation that under different conditions.
+
+pin_project! { //~ ERROR E0119
+ struct Bar<T, U> {
+ #[pin]
+ future: T,
+ field: U,
+ }
+}
+
+// conflicting implementations
+impl<T, U> Unpin for Bar<T, U> {} // Non-conditional Unpin impl
+
+pin_project! { //~ ERROR E0119
+ struct Baz<T, U> {
+ #[pin]
+ future: T,
+ field: U,
+ }
+}
+
+// conflicting implementations
+impl<T: Unpin, U: Unpin> Unpin for Baz<T, U> {} // Conditional Unpin impl
+
+fn main() {}
diff --git a/tests/ui/conflict-unpin.stderr b/tests/ui/conflict-unpin.stderr
new file mode 100644
index 0000000..546dafd
--- /dev/null
+++ b/tests/ui/conflict-unpin.stderr
@@ -0,0 +1,50 @@
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Foo<_, _>`:
+ --> $DIR/conflict-unpin.rs:5:1
+ |
+5 | / pin_project! { //~ ERROR E0119
+6 | | struct Foo<T, U> {
+7 | | #[pin]
+8 | | future: T,
+9 | | field: U,
+10 | | }
+11 | | }
+ | |_^ conflicting implementation for `Foo<_, _>`
+...
+14 | impl<T, U> Unpin for Foo<T, U> where T: Unpin {} // Conditional Unpin impl
+ | --------------------------------------------- first implementation here
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Bar<_, _>`:
+ --> $DIR/conflict-unpin.rs:18:1
+ |
+18 | / pin_project! { //~ ERROR E0119
+19 | | struct Bar<T, U> {
+20 | | #[pin]
+21 | | future: T,
+22 | | field: U,
+23 | | }
+24 | | }
+ | |_^ conflicting implementation for `Bar<_, _>`
+...
+27 | impl<T, U> Unpin for Bar<T, U> {} // Non-conditional Unpin impl
+ | ------------------------------ first implementation here
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Baz<_, _>`:
+ --> $DIR/conflict-unpin.rs:29:1
+ |
+29 | / pin_project! { //~ ERROR E0119
+30 | | struct Baz<T, U> {
+31 | | #[pin]
+32 | | future: T,
+33 | | field: U,
+34 | | }
+35 | | }
+ | |_^ conflicting implementation for `Baz<_, _>`
+...
+38 | impl<T: Unpin, U: Unpin> Unpin for Baz<T, U> {} // Conditional Unpin impl
+ | -------------------------------------------- first implementation here
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/invalid-bounds.rs b/tests/ui/invalid-bounds.rs
new file mode 100644
index 0000000..64b397a
--- /dev/null
+++ b/tests/ui/invalid-bounds.rs
@@ -0,0 +1,93 @@
+use pin_project_lite::pin_project;
+
+pin_project! {
+ struct Generics1<T: 'static : Sized> { //~ ERROR no rules expected the token `:`
+ field: T,
+ }
+}
+
+pin_project! {
+ struct Generics2<T: 'static : ?Sized> { //~ ERROR no rules expected the token `:`
+ field: T,
+ }
+}
+
+pin_project! {
+ struct Generics3<T: Sized : 'static> { //~ ERROR expected one of `+`, `,`, `=`, or `>`, found `:`
+ field: T,
+ }
+}
+
+pin_project! {
+ struct Generics4<T: ?Sized : 'static> { //~ ERROR expected one of `+`, `,`, `=`, or `>`, found `:`
+ field: T,
+ }
+}
+
+pin_project! {
+ struct Generics5<T: Sized : ?Sized> { //~ ERROR expected one of `+`, `,`, `=`, or `>`, found `:`
+ field: T,
+ }
+}
+
+pin_project! {
+ struct Generics6<T: ?Sized : Sized> { //~ ERROR no rules expected the token `Sized`
+ field: T,
+ }
+}
+
+pin_project! {
+ struct WhereClause1<T>
+ where
+ T: 'static : Sized //~ ERROR no rules expected the token `:`
+ {
+ field: T,
+ }
+}
+
+pin_project! {
+ struct WhereClause2<T>
+ where
+ T: 'static : ?Sized //~ ERROR no rules expected the token `:`
+ {
+ field: T,
+ }
+}
+
+pin_project! {
+ struct WhereClause3<T>
+ where
+ T: Sized : 'static //~ ERROR expected `where`, or `{` after struct name, found `:`
+ {
+ field: T,
+ }
+}
+
+pin_project! {
+ struct WhereClause4<T>
+ where
+ T: ?Sized : 'static //~ ERROR expected `where`, or `{` after struct name, found `:`
+ {
+ field: T,
+ }
+}
+
+pin_project! {
+ struct WhereClause5<T>
+ where
+ T: Sized : ?Sized //~ ERROR expected `where`, or `{` after struct name, found `:`
+ {
+ field: T,
+ }
+}
+
+pin_project! {
+ struct WhereClause6<T>
+ where
+ T: ?Sized : Sized //~ ERROR no rules expected the token `Sized`
+ {
+ field: T,
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/invalid-bounds.stderr b/tests/ui/invalid-bounds.stderr
new file mode 100644
index 0000000..59e9b13
--- /dev/null
+++ b/tests/ui/invalid-bounds.stderr
@@ -0,0 +1,134 @@
+error: no rules expected the token `:`
+ --> $DIR/invalid-bounds.rs:4:33
+ |
+4 | struct Generics1<T: 'static : Sized> { //~ ERROR no rules expected the token `:`
+ | ^ no rules expected this token in macro call
+
+error: no rules expected the token `:`
+ --> $DIR/invalid-bounds.rs:10:33
+ |
+10 | struct Generics2<T: 'static : ?Sized> { //~ ERROR no rules expected the token `:`
+ | ^ no rules expected this token in macro call
+
+error: expected one of `+`, `,`, `=`, or `>`, found `:`
+ --> $DIR/invalid-bounds.rs:15:1
+ |
+15 | / pin_project! {
+16 | | struct Generics3<T: Sized : 'static> { //~ ERROR expected one of `+`, `,`, `=`, or `>`, found `:`
+17 | | field: T,
+18 | | }
+19 | | }
+ | | ^
+ | | |
+ | | expected one of `+`, `,`, `=`, or `>`
+ | |_unexpected token
+ | in this macro invocation
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: expected one of `+`, `,`, `=`, or `>`, found `:`
+ --> $DIR/invalid-bounds.rs:21:1
+ |
+21 | / pin_project! {
+22 | | struct Generics4<T: ?Sized : 'static> { //~ ERROR expected one of `+`, `,`, `=`, or `>`, found `:`
+23 | | field: T,
+24 | | }
+25 | | }
+ | | ^
+ | | |
+ | | expected one of `+`, `,`, `=`, or `>`
+ | |_unexpected token
+ | in this macro invocation
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: expected one of `+`, `,`, `=`, or `>`, found `:`
+ --> $DIR/invalid-bounds.rs:27:1
+ |
+27 | / pin_project! {
+28 | | struct Generics5<T: Sized : ?Sized> { //~ ERROR expected one of `+`, `,`, `=`, or `>`, found `:`
+29 | | field: T,
+30 | | }
+31 | | }
+ | | ^
+ | | |
+ | | expected one of `+`, `,`, `=`, or `>`
+ | |_unexpected token
+ | in this macro invocation
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: no rules expected the token `Sized`
+ --> $DIR/invalid-bounds.rs:34:34
+ |
+34 | struct Generics6<T: ?Sized : Sized> { //~ ERROR no rules expected the token `Sized`
+ | ^^^^^ no rules expected this token in macro call
+
+error: no rules expected the token `:`
+ --> $DIR/invalid-bounds.rs:42:20
+ |
+42 | T: 'static : Sized //~ ERROR no rules expected the token `:`
+ | ^ no rules expected this token in macro call
+
+error: no rules expected the token `:`
+ --> $DIR/invalid-bounds.rs:51:20
+ |
+51 | T: 'static : ?Sized //~ ERROR no rules expected the token `:`
+ | ^ no rules expected this token in macro call
+
+error: expected `where`, or `{` after struct name, found `:`
+ --> $DIR/invalid-bounds.rs:57:1
+ |
+57 | / pin_project! {
+58 | | struct WhereClause3<T>
+59 | | where
+60 | | T: Sized : 'static //~ ERROR expected `where`, or `{` after struct name, found `:`
+... |
+63 | | }
+64 | | }
+ | | ^
+ | | |
+ | |_expected `where`, or `{` after struct name
+ | in this macro invocation
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: expected `where`, or `{` after struct name, found `:`
+ --> $DIR/invalid-bounds.rs:66:1
+ |
+66 | / pin_project! {
+67 | | struct WhereClause4<T>
+68 | | where
+69 | | T: ?Sized : 'static //~ ERROR expected `where`, or `{` after struct name, found `:`
+... |
+72 | | }
+73 | | }
+ | | ^
+ | | |
+ | |_expected `where`, or `{` after struct name
+ | in this macro invocation
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: expected `where`, or `{` after struct name, found `:`
+ --> $DIR/invalid-bounds.rs:75:1
+ |
+75 | / pin_project! {
+76 | | struct WhereClause5<T>
+77 | | where
+78 | | T: Sized : ?Sized //~ ERROR expected `where`, or `{` after struct name, found `:`
+... |
+81 | | }
+82 | | }
+ | | ^
+ | | |
+ | |_expected `where`, or `{` after struct name
+ | in this macro invocation
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: no rules expected the token `Sized`
+ --> $DIR/invalid-bounds.rs:87:21
+ |
+87 | T: ?Sized : Sized //~ ERROR no rules expected the token `Sized`
+ | ^^^^^ no rules expected this token in macro call
diff --git a/tests/ui/invalid.rs b/tests/ui/invalid.rs
new file mode 100644
index 0000000..e0ea61d
--- /dev/null
+++ b/tests/ui/invalid.rs
@@ -0,0 +1,25 @@
+use pin_project_lite::pin_project;
+
+pin_project! {
+ struct A<T> {
+ #[pin()] //~ ERROR no rules expected the token `(`
+ pinned: T,
+ }
+}
+
+pin_project! {
+ #[pin] //~ ERROR cannot find attribute `pin` in this scope
+ struct B<T> {
+ pinned: T,
+ }
+}
+
+pin_project! {
+ struct C<T> {
+ #[pin]
+ #[pin] //~ ERROR no rules expected the token `#`
+ pinned: T,
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/invalid.stderr b/tests/ui/invalid.stderr
new file mode 100644
index 0000000..f780e2e
--- /dev/null
+++ b/tests/ui/invalid.stderr
@@ -0,0 +1,17 @@
+error: no rules expected the token `(`
+ --> $DIR/invalid.rs:5:14
+ |
+5 | #[pin()] //~ ERROR no rules expected the token `(`
+ | ^ no rules expected this token in macro call
+
+error: no rules expected the token `#`
+ --> $DIR/invalid.rs:20:9
+ |
+20 | #[pin] //~ ERROR no rules expected the token `#`
+ | ^ no rules expected this token in macro call
+
+error: cannot find attribute `pin` in this scope
+ --> $DIR/invalid.rs:11:7
+ |
+11 | #[pin] //~ ERROR cannot find attribute `pin` in this scope
+ | ^^^
diff --git a/tests/ui/overlapping_lifetime_names.rs b/tests/ui/overlapping_lifetime_names.rs
new file mode 100644
index 0000000..87a737e
--- /dev/null
+++ b/tests/ui/overlapping_lifetime_names.rs
@@ -0,0 +1,10 @@
+use pin_project_lite::pin_project;
+
+pin_project! { //~ ERROR E0496
+ pub struct Foo<'__pin, T> { //~ ERROR E0263
+ #[pin]
+ field: &'__pin mut T,
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/overlapping_lifetime_names.stderr b/tests/ui/overlapping_lifetime_names.stderr
new file mode 100644
index 0000000..f86942c
--- /dev/null
+++ b/tests/ui/overlapping_lifetime_names.stderr
@@ -0,0 +1,75 @@
+error[E0496]: lifetime name `'__pin` shadows a lifetime name that is already in scope
+ --> $DIR/overlapping_lifetime_names.rs:3:1
+ |
+3 | / pin_project! { //~ ERROR E0496
+4 | | pub struct Foo<'__pin, T> { //~ ERROR E0263
+ | | ------ first declared here
+5 | | #[pin]
+6 | | field: &'__pin mut T,
+7 | | }
+8 | | }
+ | |_^ lifetime '__pin already in scope
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0496]: lifetime name `'__pin` shadows a lifetime name that is already in scope
+ --> $DIR/overlapping_lifetime_names.rs:3:1
+ |
+3 | / pin_project! { //~ ERROR E0496
+4 | | pub struct Foo<'__pin, T> { //~ ERROR E0263
+ | | ------ first declared here
+5 | | #[pin]
+6 | | field: &'__pin mut T,
+7 | | }
+8 | | }
+ | |_^ lifetime '__pin already in scope
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0263]: lifetime name `'__pin` declared twice in the same scope
+ --> $DIR/overlapping_lifetime_names.rs:4:20
+ |
+3 | / pin_project! { //~ ERROR E0496
+4 | | pub struct Foo<'__pin, T> { //~ ERROR E0263
+ | | ^^^^^^ declared twice
+5 | | #[pin]
+6 | | field: &'__pin mut T,
+7 | | }
+8 | | }
+ | |_- previous declaration here
+
+error[E0263]: lifetime name `'__pin` declared twice in the same scope
+ --> $DIR/overlapping_lifetime_names.rs:4:20
+ |
+3 | / pin_project! { //~ ERROR E0496
+4 | | pub struct Foo<'__pin, T> { //~ ERROR E0263
+ | | ^^^^^^ declared twice
+5 | | #[pin]
+6 | | field: &'__pin mut T,
+7 | | }
+8 | | }
+ | |_- previous declaration here
+
+error[E0263]: lifetime name `'__pin` declared twice in the same scope
+ --> $DIR/overlapping_lifetime_names.rs:4:20
+ |
+3 | / pin_project! { //~ ERROR E0496
+4 | | pub struct Foo<'__pin, T> { //~ ERROR E0263
+ | | ^^^^^^ declared twice
+5 | | #[pin]
+6 | | field: &'__pin mut T,
+7 | | }
+8 | | }
+ | |_- previous declaration here
+
+error[E0263]: lifetime name `'__pin` declared twice in the same scope
+ --> $DIR/overlapping_lifetime_names.rs:4:20
+ |
+3 | / pin_project! { //~ ERROR E0496
+4 | | pub struct Foo<'__pin, T> { //~ ERROR E0263
+ | | ^^^^^^ declared twice
+5 | | #[pin]
+6 | | field: &'__pin mut T,
+7 | | }
+8 | | }
+ | |_- previous declaration here
diff --git a/tests/ui/overlapping_unpin_struct.rs b/tests/ui/overlapping_unpin_struct.rs
new file mode 100644
index 0000000..1338524
--- /dev/null
+++ b/tests/ui/overlapping_unpin_struct.rs
@@ -0,0 +1,19 @@
+use pin_project_lite::pin_project;
+use std::marker::PhantomPinned;
+
+pin_project! {
+ struct Foo<T> {
+ #[pin]
+ inner: T,
+ }
+}
+
+struct __Origin {}
+
+impl Unpin for __Origin {}
+
+fn is_unpin<T: Unpin>() {}
+
+fn main() {
+ is_unpin::<Foo<PhantomPinned>>(); //~ ERROR E0277
+}
diff --git a/tests/ui/overlapping_unpin_struct.stderr b/tests/ui/overlapping_unpin_struct.stderr
new file mode 100644
index 0000000..b944b0f
--- /dev/null
+++ b/tests/ui/overlapping_unpin_struct.stderr
@@ -0,0 +1,11 @@
+error[E0277]: `std::marker::PhantomPinned` cannot be unpinned
+ --> $DIR/overlapping_unpin_struct.rs:18:5
+ |
+15 | fn is_unpin<T: Unpin>() {}
+ | ----- required by this bound in `is_unpin`
+...
+18 | is_unpin::<Foo<PhantomPinned>>(); //~ ERROR E0277
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `_::__Origin<'_, std::marker::PhantomPinned>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned`
+ |
+ = note: required because it appears within the type `_::__Origin<'_, std::marker::PhantomPinned>`
+ = note: required because of the requirements on the impl of `std::marker::Unpin` for `Foo<std::marker::PhantomPinned>`
diff --git a/tests/ui/packed.rs b/tests/ui/packed.rs
new file mode 100644
index 0000000..0bccc1f
--- /dev/null
+++ b/tests/ui/packed.rs
@@ -0,0 +1,19 @@
+use pin_project_lite::pin_project;
+
+pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
+ #[repr(packed, C)]
+ struct A {
+ #[pin]
+ field: u16,
+ }
+}
+
+pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
+ #[repr(packed(2))]
+ struct C {
+ #[pin]
+ field: u32,
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/packed.stderr b/tests/ui/packed.stderr
new file mode 100644
index 0000000..a976163
--- /dev/null
+++ b/tests/ui/packed.stderr
@@ -0,0 +1,55 @@
+error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
+ --> $DIR/packed.rs:3:1
+ |
+3 | / pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
+4 | | #[repr(packed, C)]
+5 | | struct A {
+6 | | #[pin]
+7 | | field: u16,
+8 | | }
+9 | | }
+ | |_^
+ |
+note: the lint level is defined here
+ --> $DIR/packed.rs:3:1
+ |
+3 | / pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
+4 | | #[repr(packed, C)]
+5 | | struct A {
+6 | | #[pin]
+7 | | field: u16,
+8 | | }
+9 | | }
+ | |_^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
+ = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
+ --> $DIR/packed.rs:11:1
+ |
+11 | / pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
+12 | | #[repr(packed(2))]
+13 | | struct C {
+14 | | #[pin]
+15 | | field: u32,
+16 | | }
+17 | | }
+ | |_^
+ |
+note: the lint level is defined here
+ --> $DIR/packed.rs:11:1
+ |
+11 | / pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
+12 | | #[repr(packed(2))]
+13 | | struct C {
+14 | | #[pin]
+15 | | field: u32,
+16 | | }
+17 | | }
+ | |_^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
+ = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/proper_unpin.rs b/tests/ui/proper_unpin.rs
new file mode 100644
index 0000000..3c85f2d
--- /dev/null
+++ b/tests/ui/proper_unpin.rs
@@ -0,0 +1,41 @@
+use pin_project_lite::pin_project;
+use std::marker::PhantomPinned;
+
+struct Inner<T> {
+ val: T,
+}
+
+pin_project! {
+ struct Foo<T, U> {
+ #[pin]
+ inner: Inner<T>,
+ other: U,
+ }
+}
+
+pin_project! {
+ pub struct TrivialBounds {
+ #[pin]
+ field1: PhantomPinned,
+ }
+}
+
+pin_project! {
+ struct Bar<'a, T, U> {
+ #[pin]
+ inner: &'a mut Inner<T>,
+ other: U,
+ }
+}
+
+fn is_unpin<T: Unpin>() {}
+
+fn main() {
+ is_unpin::<Foo<PhantomPinned, ()>>(); //~ ERROR E0277
+ is_unpin::<Foo<(), PhantomPinned>>(); // Ok
+ is_unpin::<Foo<PhantomPinned, PhantomPinned>>(); //~ ERROR E0277
+
+ is_unpin::<TrivialBounds>(); //~ ERROR E0277
+
+ is_unpin::<Bar<'_, PhantomPinned, PhantomPinned>>(); //~ Ok
+}
diff --git a/tests/ui/proper_unpin.stderr b/tests/ui/proper_unpin.stderr
new file mode 100644
index 0000000..8149918
--- /dev/null
+++ b/tests/ui/proper_unpin.stderr
@@ -0,0 +1,37 @@
+error[E0277]: `std::marker::PhantomPinned` cannot be unpinned
+ --> $DIR/proper_unpin.rs:34:5
+ |
+31 | fn is_unpin<T: Unpin>() {}
+ | ----- required by this bound in `is_unpin`
+...
+34 | is_unpin::<Foo<PhantomPinned, ()>>(); //~ ERROR E0277
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `_::__Origin<'_, std::marker::PhantomPinned, ()>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned`
+ |
+ = note: required because it appears within the type `Inner<std::marker::PhantomPinned>`
+ = note: required because it appears within the type `_::__Origin<'_, std::marker::PhantomPinned, ()>`
+ = note: required because of the requirements on the impl of `std::marker::Unpin` for `Foo<std::marker::PhantomPinned, ()>`
+
+error[E0277]: `std::marker::PhantomPinned` cannot be unpinned
+ --> $DIR/proper_unpin.rs:36:5
+ |
+31 | fn is_unpin<T: Unpin>() {}
+ | ----- required by this bound in `is_unpin`
+...
+36 | is_unpin::<Foo<PhantomPinned, PhantomPinned>>(); //~ ERROR E0277
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `_::__Origin<'_, std::marker::PhantomPinned, std::marker::PhantomPinned>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned`
+ |
+ = note: required because it appears within the type `Inner<std::marker::PhantomPinned>`
+ = note: required because it appears within the type `_::__Origin<'_, std::marker::PhantomPinned, std::marker::PhantomPinned>`
+ = note: required because of the requirements on the impl of `std::marker::Unpin` for `Foo<std::marker::PhantomPinned, std::marker::PhantomPinned>`
+
+error[E0277]: `std::marker::PhantomPinned` cannot be unpinned
+ --> $DIR/proper_unpin.rs:38:5
+ |
+31 | fn is_unpin<T: Unpin>() {}
+ | ----- required by this bound in `is_unpin`
+...
+38 | is_unpin::<TrivialBounds>(); //~ ERROR E0277
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ within `_::__Origin<'_>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned`
+ |
+ = note: required because it appears within the type `_::__Origin<'_>`
+ = note: required because of the requirements on the impl of `std::marker::Unpin` for `TrivialBounds`
diff --git a/tests/ui/unpin_sneaky.rs b/tests/ui/unpin_sneaky.rs
new file mode 100644
index 0000000..984cc2a
--- /dev/null
+++ b/tests/ui/unpin_sneaky.rs
@@ -0,0 +1,12 @@
+use pin_project_lite::pin_project;
+
+pin_project! {
+ struct Foo {
+ #[pin]
+ inner: u8,
+ }
+}
+
+impl Unpin for __Origin {} //~ ERROR E0412,E0321
+
+fn main() {}
diff --git a/tests/ui/unpin_sneaky.stderr b/tests/ui/unpin_sneaky.stderr
new file mode 100644
index 0000000..77ad2dc
--- /dev/null
+++ b/tests/ui/unpin_sneaky.stderr
@@ -0,0 +1,11 @@
+error[E0412]: cannot find type `__Origin` in this scope
+ --> $DIR/unpin_sneaky.rs:10:16
+ |
+10 | impl Unpin for __Origin {} //~ ERROR E0412,E0321
+ | ^^^^^^^^ not found in this scope
+
+error[E0321]: cross-crate traits with a default impl, like `std::marker::Unpin`, can only be implemented for a struct/enum type, not `[type error]`
+ --> $DIR/unpin_sneaky.rs:10:1
+ |
+10 | impl Unpin for __Origin {} //~ ERROR E0412,E0321
+ | ^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
diff --git a/tests/ui/unsupported.rs b/tests/ui/unsupported.rs
new file mode 100644
index 0000000..2f80836
--- /dev/null
+++ b/tests/ui/unsupported.rs
@@ -0,0 +1,27 @@
+use pin_project_lite::pin_project;
+
+pin_project! {
+ struct Struct1 {} //~ ERROR no rules expected the token `}`
+}
+
+pin_project! {
+ struct Struct2(); //~ ERROR no rules expected the token `(`
+}
+
+pin_project! {
+ struct Struct3; //~ ERROR no rules expected the token `;`
+}
+
+pin_project! {
+ enum Enum { //~ ERROR no rules expected the token `enum`
+ A(u8)
+ }
+}
+
+pin_project! {
+ union Union { //~ ERROR no rules expected the token `union`
+ x: u8,
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/unsupported.stderr b/tests/ui/unsupported.stderr
new file mode 100644
index 0000000..4f7b1ae
--- /dev/null
+++ b/tests/ui/unsupported.stderr
@@ -0,0 +1,29 @@
+error: no rules expected the token `}`
+ --> $DIR/unsupported.rs:4:21
+ |
+4 | struct Struct1 {} //~ ERROR no rules expected the token `}`
+ | ^ no rules expected this token in macro call
+
+error: no rules expected the token `(`
+ --> $DIR/unsupported.rs:8:19
+ |
+8 | struct Struct2(); //~ ERROR no rules expected the token `(`
+ | ^ no rules expected this token in macro call
+
+error: no rules expected the token `;`
+ --> $DIR/unsupported.rs:12:19
+ |
+12 | struct Struct3; //~ ERROR no rules expected the token `;`
+ | ^ no rules expected this token in macro call
+
+error: no rules expected the token `enum`
+ --> $DIR/unsupported.rs:16:5
+ |
+16 | enum Enum { //~ ERROR no rules expected the token `enum`
+ | ^^^^ no rules expected this token in macro call
+
+error: no rules expected the token `union`
+ --> $DIR/unsupported.rs:22:5
+ |
+22 | union Union { //~ ERROR no rules expected the token `union`
+ | ^^^^^ no rules expected this token in macro call