aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChih-Hung Hsieh <chh@google.com>2020-10-29 20:20:56 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-10-29 20:20:56 +0000
commit56b526e0d7d3aaa56d8c157819482e09eb526869 (patch)
tree1665fba53d0ef006d925ffdd9cebe6819cac8e28
parent665a42e1c33934ca1891bc2ee5a58da6a4489ac9 (diff)
parentb664d2ad134bfcf090a4b7bd632525193b58890a (diff)
downloadpin-project-lite-56b526e0d7d3aaa56d8c157819482e09eb526869.tar.gz
Upgrade rust/crates/pin-project-lite to 0.1.11 am: 5bb3e83361 am: 6f7680c3e8 am: b664d2ad13
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/pin-project-lite/+/1475559 Change-Id: Ice138897a46b210978fd39725fa2e87de8bf9e1f
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--.editorconfig3
-rw-r--r--.github/workflows/ci.yml84
-rw-r--r--.gitignore2
-rw-r--r--CHANGELOG.md27
-rw-r--r--CODE_OF_CONDUCT.md9
-rw-r--r--Cargo.toml9
-rw-r--r--Cargo.toml.orig8
-rw-r--r--LICENSE-APACHE25
-rw-r--r--METADATA8
-rw-r--r--README.md8
-rw-r--r--ci/check-minimal-versions.sh27
-rwxr-xr-x[-rw-r--r--]ci/install-component.sh31
-rwxr-xr-x[-rw-r--r--]ci/install-rust.sh3
-rw-r--r--rustfmt.toml2
-rw-r--r--scripts/README.md3
-rwxr-xr-xscripts/check-minimal-versions.sh58
-rwxr-xr-xscripts/ci.sh37
-rwxr-xr-xscripts/expandtest.sh35
-rw-r--r--src/lib.rs723
-rw-r--r--src/lib.rs.orig618
-rw-r--r--tests/auxiliary/mod.rs12
-rw-r--r--tests/lint.rs134
-rw-r--r--tests/lint.txt24
-rw-r--r--tests/proper_unpin.rs49
-rw-r--r--tests/test.rs203
-rw-r--r--tests/ui/overlapping_unpin_struct.stderr8
-rw-r--r--tests/ui/proper_unpin.rs41
-rw-r--r--tests/ui/proper_unpin.stderr37
-rw-r--r--tests/ui/unpin_sneaky.stderr2
30 files changed, 1474 insertions, 758 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 416a9fb..dff72dd 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
{
"git": {
- "sha1": "5859acd41133d479638abccea409ac0f64b0ef77"
+ "sha1": "afa54fe19f0a7629b874fb7d4b825e806596ef10"
}
}
diff --git a/.editorconfig b/.editorconfig
index c93ffc7..933a9a4 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -14,3 +14,6 @@ indent_size = 4
[*.{json,yml,md}]
indent_size = 2
+
+[*.sh]
+switch_case_indent = true
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 329896b..aa2394e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -6,9 +6,8 @@ on:
branches:
- master
- staging
- - trying
schedule:
- - cron: '00 01 * * *'
+ - cron: '0 1 * * *'
env:
RUSTFLAGS: -Dwarnings
@@ -34,57 +33,42 @@ jobs:
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
+ run: ci/install-rust.sh ${{ matrix.rust }}
+ - if: matrix.rust == 'nightly'
+ run: cargo install cargo-hack
+ - run: rustup target add thumbv7m-none-eabi
+ - run: cargo test --all --exclude expandtest
+ - run: cargo check --manifest-path tests/no-std/Cargo.toml --target thumbv7m-none-eabi
+ - if: matrix.rust == 'nightly'
+ run: bash scripts/check-minimal-versions.sh
+
+ expandtest:
+ name: expandtest
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Install Rust and Rustfmt
+ run: ci/install-component.sh rustfmt
+ - run: cargo install cargo-expand
+ - run: bash scripts/expandtest.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
+ - name: Install Rust and Clippy
+ run: ci/install-component.sh 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
+ - name: Install Rust and Rustfmt
+ run: ci/install-component.sh rustfmt
+ - run: cargo fmt --all -- --check
rustdoc:
name: rustdoc
@@ -94,11 +78,15 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Install Rust
- run: |
- . ./ci/install-rust.sh
- - name: cargo doc
- run: |
- cargo doc --no-deps --all --all-features
+ run: ci/install-rust.sh
+ - run: cargo doc --no-deps --all --all-features
+
+ shellcheck:
+ name: shellcheck
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - run: shellcheck **/*.sh
# 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
@@ -111,9 +99,11 @@ jobs:
if: github.event_name == 'push' && success()
needs:
- test
+ - expandtest
- clippy
- rustfmt
- rustdoc
+ - shellcheck
runs-on: ubuntu-latest
steps:
- name: Mark the job as a success
@@ -123,9 +113,11 @@ jobs:
if: github.event_name == 'push' && !success()
needs:
- test
+ - expandtest
- clippy
- rustfmt
- rustdoc
+ - shellcheck
runs-on: ubuntu-latest
steps:
- name: Mark the job as a failure
diff --git a/.gitignore b/.gitignore
index 214d7a8..ad0f684 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,4 @@ 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
+# Refs: https://docs.github.com/en/free-pro-team@latest/github/using-git/ignoring-files#configuring-ignored-files-for-all-repositories-on-your-computer
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 17b1f87..8c8087f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,27 @@ This project adheres to [Semantic Versioning](https://semver.org).
## [Unreleased]
+## [0.1.11] - 2020-10-20
+
+* Suppress `clippy::redundant_pub_crate` lint in generated code.
+
+* Documentation improvements.
+
+## [0.1.10] - 2020-10-01
+
+* Suppress `drop_bounds` lint, which will be added to rustc in the future. See [taiki-e/pin-project#272](https://github.com/taiki-e/pin-project/issues/272) for more details.
+
+## [0.1.9] - 2020-09-29
+
+* Fix trailing comma support in generics
+
+## [0.1.8] - 2020-09-26
+
+* Fix compatibility of generated code with `forbid(future_incompatible)`
+
+ Note: This does not guarantee compatibility with `forbid(future_incompatible)` in the future.
+ If rustc adds a new lint, we may not be able to keep this.
+
## [0.1.7] - 2020-06-04
* [Support `?Sized` bounds in where clauses.][22]
@@ -61,7 +82,11 @@ This project adheres to [Semantic Versioning](https://semver.org).
Initial release
-[Unreleased]: https://github.com/taiki-e/pin-project-lite/compare/v0.1.7...HEAD
+[Unreleased]: https://github.com/taiki-e/pin-project-lite/compare/v0.1.11...HEAD
+[0.1.11]: https://github.com/taiki-e/pin-project-lite/compare/v0.1.10...v0.1.11
+[0.1.10]: https://github.com/taiki-e/pin-project-lite/compare/v0.1.9...v0.1.10
+[0.1.9]: https://github.com/taiki-e/pin-project-lite/compare/v0.1.8...v0.1.9
+[0.1.8]: https://github.com/taiki-e/pin-project-lite/compare/v0.1.7...v0.1.8
[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
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..70c2090
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,9 @@
+# Code of Conduct
+
+This project adheres to the [Rust Code of Conduct].
+
+## Enforcement
+
+If you believe someone is violating the code of conduct, we ask that you report it by contacting taiki-e (te316e89@gmail.com).
+
+[Rust Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct
diff --git a/Cargo.toml b/Cargo.toml
index cd34113..2fecadc 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "pin-project-lite"
-version = "0.1.7"
+version = "0.1.11"
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"
@@ -28,7 +28,10 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
[dev-dependencies.rustversion]
-version = "1.0"
+version = "1"
+
+[dev-dependencies.static_assertions]
+version = "1"
[dev-dependencies.trybuild]
-version = "1.0"
+version = "1"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 4d42294..e279d86 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "pin-project-lite"
-version = "0.1.7"
+version = "0.1.11"
authors = ["Taiki Endo <te316e89@gmail.com>"]
edition = "2018"
license = "Apache-2.0 OR MIT"
@@ -20,6 +20,7 @@ targets = ["x86_64-unknown-linux-gnu"]
[workspace]
members = [
"tests/doc",
+ "tests/expand",
"tests/no-core",
"tests/no-std",
]
@@ -27,5 +28,6 @@ members = [
[dependencies]
[dev-dependencies]
-rustversion = "1.0"
-trybuild = "1.0"
+rustversion = "1"
+static_assertions = "1"
+trybuild = "1"
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
index d645695..f433b1a 100644
--- a/LICENSE-APACHE
+++ b/LICENSE-APACHE
@@ -175,28 +175,3 @@
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/METADATA b/METADATA
index 4a34a42..68b46ad 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/pin-project-lite/pin-project-lite-0.1.7.crate"
+ value: "https://static.crates.io/crates/pin-project-lite/pin-project-lite-0.1.11.crate"
}
- version: "0.1.7"
+ version: "0.1.11"
license_type: NOTICE
last_upgrade_date {
year: 2020
- month: 9
- day: 17
+ month: 10
+ day: 26
}
}
diff --git a/README.md b/README.md
index faec117..b6c5b3a 100644
--- a/README.md
+++ b/README.md
@@ -89,11 +89,11 @@ pin-project supports this by [`UnsafeUnpin`][unsafe-unpin] and [`!Unpin`][not-un
[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
+[naming]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html
+[not-unpin]: https://docs.rs/pin-project/1/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
+[pinned-drop]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#pinned_drop
+[unsafe-unpin]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unsafeunpin
## License
diff --git a/ci/check-minimal-versions.sh b/ci/check-minimal-versions.sh
deleted file mode 100644
index 6152c15..0000000
--- a/ci/check-minimal-versions.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/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
index 9aaa5ce..dbba7b1 100644..100755
--- a/ci/install-component.sh
+++ b/ci/install-component.sh
@@ -1,22 +1,27 @@
#!/bin/bash
+# Install nightly Rust with a given component.
+#
+# If the component is unavailable on the latest nightly,
+# use the latest toolchain with the component available.
+#
+# When using stable Rust, this script is basically unnecessary as almost components available.
+#
+# Refs: https://github.com/rust-lang/rustup-components-history#the-web-part
+
set -euo pipefail
-component="${1}"
+package="${1:?}"
+target="${2:-x86_64-unknown-linux-gnu}"
-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"
+date=$(curl -sSf https://rust-lang.github.io/rustup-components-history/"${target}"/"${package}")
- . ci/install-rust.sh "nightly-${target}"
+# shellcheck disable=1090
+"$(cd "$(dirname "${0}")" && pwd)"/install-rust.sh nightly-"${date}"
- rustup component add "${component}"
-fi
+rustup component add "${package}"
-case "${component}" in
- rustfmt) "${component}" -V ;;
- *) cargo "${component}" -V ;;
+case "${package}" in
+ rustfmt) "${package}" -V ;;
+ *) cargo "${package}" -V ;;
esac
diff --git a/ci/install-rust.sh b/ci/install-rust.sh
index b6625b6..92c5877 100644..100755
--- a/ci/install-rust.sh
+++ b/ci/install-rust.sh
@@ -4,8 +4,7 @@ set -euo pipefail
toolchain="${1:-nightly}"
-rustup set profile minimal
-rustup update "${toolchain}" --no-self-update
+rustup toolchain install "${toolchain}" --no-self-update --profile minimal
rustup default "${toolchain}"
rustup -V
diff --git a/rustfmt.toml b/rustfmt.toml
index d51f11e..18c6d2a 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -5,6 +5,8 @@
# first version.
# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3383).
version = "Two"
+# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3391)
+error_on_line_overflow = true
# Override the default formatting style.
# See https://internals.rust-lang.org/t/running-rustfmt-on-rust-lang-rust-and-other-rust-lang-repositories/8732/81.
diff --git a/scripts/README.md b/scripts/README.md
new file mode 100644
index 0000000..671a9b1
--- /dev/null
+++ b/scripts/README.md
@@ -0,0 +1,3 @@
+This directory contains scripts used by the developers of this project.
+
+Some scripts in this directory are also used in CI, but scripts intended to be used only in CI and scripts not intended to be used directly by the developers are basically in the `ci` directory.
diff --git a/scripts/check-minimal-versions.sh b/scripts/check-minimal-versions.sh
new file mode 100755
index 0000000..7d16e93
--- /dev/null
+++ b/scripts/check-minimal-versions.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+# Check all public crates with minimal version dependencies.
+#
+# Usage:
+# bash scripts/check-minimal-versions.sh [check|test]
+#
+# Note:
+# - This script modifies Cargo.toml and Cargo.lock while running
+# - This script exits with 1 if there are any unstaged changes
+# - This script requires nightly Rust and cargo-hack
+#
+# Refs: https://github.com/rust-lang/cargo/issues/5657
+
+set -euo pipefail
+
+cd "$(cd "$(dirname "${0}")" && pwd)"/..
+
+# Decide Rust toolchain.
+# If the `CI` environment variable is not set to `true`, then nightly is used by default.
+if [[ "${1:-none}" == "+"* ]]; then
+ toolchain="${1}"
+ shift
+elif [[ "${CI:-false}" != "true" ]]; then
+ cargo +nightly -V >/dev/null || exit 1
+ toolchain="+nightly"
+fi
+# This script requires nightly Rust and cargo-hack
+if [[ "${toolchain:-+nightly}" != "+nightly"* ]] || ! cargo hack -V &>/dev/null; then
+ echo "error: check-minimal-versions.sh requires nightly Rust and cargo-hack"
+ exit 1
+fi
+
+subcmd="${1:-check}"
+case "${subcmd}" in
+ check | test) ;;
+ *)
+ echo "error: invalid argument \`${1}\`"
+ exit 1
+ ;;
+esac
+
+# This script modifies Cargo.toml and Cargo.lock, so make sure there are no
+# unstaged changes.
+git diff --exit-code
+# Restore original Cargo.toml and Cargo.lock on exit.
+trap 'git checkout .' EXIT
+
+if [[ "${subcmd}" == "check" ]]; then
+ # 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
+fi
+
+# Update Cargo.lock to minimal version dependencies.
+cargo ${toolchain:-} update -Zminimal-versions
+# Run check for all public members of the workspace.
+cargo ${toolchain:-} hack "${subcmd}" --workspace --all-features --ignore-private -Zfeatures=all
diff --git a/scripts/ci.sh b/scripts/ci.sh
new file mode 100755
index 0000000..ec08568
--- /dev/null
+++ b/scripts/ci.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+# A script to run a simplified version of the checks done by CI.
+#
+# Usage:
+# bash scripts/ci.sh
+#
+# Note: This script requires nightly Rust, rustfmt, clippy, and cargo-expand
+
+set -euo pipefail
+
+if [[ "${1:-none}" == "+"* ]]; then
+ toolchain="${1}"
+else
+ cargo +nightly -V >/dev/null || exit 1
+ toolchain="+nightly"
+fi
+
+if [[ "${toolchain:-+nightly}" != "+nightly"* ]] || ! rustfmt -V &>/dev/null || ! cargo clippy -V &>/dev/null || ! cargo expand -V &>/dev/null; then
+ echo "error: ci.sh requires nightly Rust, rustfmt, clippy, and cargo-expand"
+ exit 1
+fi
+
+echo "Running 'cargo ${toolchain} fmt --all'"
+cargo "${toolchain}" fmt --all
+
+echo "Running 'cargo ${toolchain} clippy --all --all-targets'"
+cargo "${toolchain}" clippy --all --all-features --all-targets -Zunstable-options
+
+echo "Running 'cargo ${toolchain} test --all --exclude expandtest'"
+TRYBUILD=overwrite cargo "${toolchain}" test --all --all-features --exclude expandtest
+
+echo "Running 'bash scripts/expandtest.sh ${toolchain}'"
+"$(cd "$(dirname "${0}")" && pwd)"/expandtest.sh "${toolchain}"
+
+echo "Running 'cargo ${toolchain} doc --no-deps --all'"
+cargo "${toolchain}" doc --no-deps --all --all-features
diff --git a/scripts/expandtest.sh b/scripts/expandtest.sh
new file mode 100755
index 0000000..844ace6
--- /dev/null
+++ b/scripts/expandtest.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+# A script to run expandtest.
+#
+# Usage:
+# bash scripts/expandtest.sh
+#
+# Note: This script requires nightly Rust, rustfmt, and cargo-expand
+
+set -euo pipefail
+
+script_dir="$(cd "$(dirname "${0}")" && pwd)"
+
+if [[ "${1:-none}" == "+"* ]]; then
+ toolchain="${1}"
+elif [[ "${CI:-false}" != "true" ]]; then
+ cargo +nightly -V >/dev/null || exit 1
+ toolchain="+nightly"
+fi
+
+if [[ "${toolchain:-+nightly}" != "+nightly"* ]] || ! rustfmt -V &>/dev/null || ! cargo expand -V &>/dev/null; then
+ echo "error: expandtest.sh requires nightly Rust, rustfmt, and cargo-expand"
+ exit 1
+fi
+
+if [[ "${CI:-false}" != "true" ]]; then
+ # First, check if the compile fails for another reason.
+ cargo ${toolchain} check --tests --manifest-path "${script_dir}"/../tests/expand/Cargo.toml
+
+ # Next, remove the `*.expanded.rs` files to allow updating those files.
+ # Refs: https://docs.rs/macrotest/1/macrotest/#updating-expandedrs
+ rm -rf "${script_dir}"/../tests/expand/tests/expand/*.expanded.rs
+fi
+
+cargo ${toolchain:-} test --manifest-path "${script_dir}"/../tests/expand/Cargo.toml
diff --git a/src/lib.rs b/src/lib.rs
index 4c70e26..03a6586 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,6 @@
//! A lightweight version of [pin-project] written with declarative macros.
//!
-//! ## Examples
+//! # Examples
//!
//! [`pin_project!`] macro creates a projection type covering all the fields of struct.
//!
@@ -25,61 +25,63 @@
//! }
//! ```
//!
-//! ## [pin-project] vs pin-project-lite
+//! # [pin-project] vs pin-project-lite
//!
//! Here are some similarities and differences compared to [pin-project].
//!
-//! ### Similar: Safety
+//! ## 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
+//! ## 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
+//! ## 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
+//! ## 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
+//! ## 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
+//! ## Different: No support for custom Drop implementation
//!
//! pin-project supports this by [`#[pinned_drop]`][pinned-drop].
//!
-//! ### Different: No support for custom Unpin implementation
+//! ## 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
+//! ## 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
+//! [naming]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html
+//! [not-unpin]: https://docs.rs/pin-project/1/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
+//! [pinned-drop]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#pinned_drop
+//! [unsafe-unpin]: https://docs.rs/pin-project/1/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(html_root_url = "https://docs.rs/pin-project-lite/0.1.11")]
#![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(future_incompatible, 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)]
+// mem::take and #[non_exhaustive] requires Rust 1.40, matches! requires Rust 1.42
+#![allow(
+ clippy::mem_replace_with_default,
+ clippy::manual_non_exhaustive,
+ clippy::match_like_matches_macro
+)]
// ANDROID: Use std to allow building as a dylib.
extern crate std;
@@ -107,14 +109,14 @@ extern crate std;
/// 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
+/// # 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
+/// # Examples
///
/// ```rust
/// use pin_project_lite::pin_project;
@@ -141,6 +143,28 @@ extern crate std;
/// original [`Pin`] type, it needs to use [`.as_mut()`][`Pin::as_mut`] to avoid
/// consuming the [`Pin`].
///
+/// ```rust
+/// use pin_project_lite::pin_project;
+/// use std::pin::Pin;
+///
+/// pin_project! {
+/// struct Struct<T> {
+/// #[pin]
+/// field: T,
+/// }
+/// }
+///
+/// impl<T> Struct<T> {
+/// fn call_project_twice(mut self: Pin<&mut Self>) {
+/// // `project` consumes `self`, so reborrow the `Pin<&mut Self>` via `as_mut`.
+/// self.as_mut().project();
+/// self.as_mut().project();
+/// }
+/// }
+/// ```
+///
+/// # `!Unpin`
+///
/// If you want to ensure that [`Unpin`] is not implemented, use `#[pin]`
/// attribute for a [`PhantomPinned`] field.
///
@@ -151,7 +175,7 @@ extern crate std;
/// pin_project! {
/// struct Struct<T> {
/// field: T,
-/// #[pin]
+/// #[pin] // <------ This `#[pin]` is required to make `Struct` to `!Unpin`.
/// _pin: PhantomPinned,
/// }
/// }
@@ -174,137 +198,23 @@ macro_rules! pin_project {
// * 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 support for `Self` in where clauses. (wontfix)
+// * no support for overlapping lifetime names. (wontfix)
// * no interoperability with other field attributes.
+// * no useful error messages. (wontfix)
// 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)?
- ),*
- )?
+ // =============================================================================================
+ // main: struct
+ (@struct_internal;
+ [$proj_vis:vis]
+ [$(#[$attrs:meta])* $vis:vis struct $ident:ident]
+ [$($def_generics:tt)*]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
{
$(
$(#[$pin:ident])?
@@ -313,48 +223,24 @@ macro_rules! __pin_project_internal {
}
) => {
$(#[$attrs])*
- $vis struct $ident $(<
- $( $lifetime $(: $lifetime_bound)? ,)*
- $( $generics
- $(: $generics_bound)?
- $(: ?$generics_unsized_bound)?
- $(: $generics_lifetime_bound)?
- $(= $generics_default)?
- ),*
- >)?
+ $vis struct $ident $($def_generics)*
$(where
- $( $where_clause_ty
- $(: $where_clause_bound)?
- $(: ?$where_clause_unsized_bound)?
- $(: $where_clause_lifetime_bound)?
- ),*
- )?
+ $($where_clause)*)?
{
$(
$field_vis $field: $field_ty
),+
}
+ #[allow(explicit_outlives_requirements)]
#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
+ #[allow(clippy::redundant_pub_crate)]
#[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)?
- ),*
- )?
+ $crate::__pin_project_internal! { @make_proj_ty_struct;
+ [$proj_vis]
+ [$vis struct $ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
{
$(
$(#[$pin])?
@@ -363,32 +249,19 @@ macro_rules! __pin_project_internal {
}
}
- impl $(<
- $( $lifetime $(: $lifetime_bound)? ,)*
- $( $generics
- $(: $generics_bound)?
- $(: ?$generics_unsized_bound)?
- $(: $generics_lifetime_bound)?
- ),*
- >)?
- $ident $(< $($lifetime,)* $($generics),* >)?
+ impl <$($impl_generics)*> $ident <$($ty_generics)*>
$(where
- $( $where_clause_ty
- $(: $where_clause_bound)?
- $(: ?$where_clause_unsized_bound)?
- $(: $where_clause_lifetime_bound)?
- ),*
- )?
+ $($where_clause)*)?
{
$proj_vis fn project<'__pin>(
self: $crate::__private::Pin<&'__pin mut Self>,
- ) -> Projection<'__pin $(, $($lifetime,)* $($generics),* )?> {
+ ) -> Projection <'__pin, $($ty_generics)*> {
unsafe {
- let this = self.get_unchecked_mut();
+ let Self { $($field),* } = self.get_unchecked_mut();
Projection {
$(
- $field: $crate::__pin_project_internal!(@make_unsafe_field_proj
- this; $(#[$pin])? $field; mut
+ $field: $crate::__pin_project_internal!(@make_unsafe_field_proj;
+ $(#[$pin])? $field
)
),+
}
@@ -396,13 +269,13 @@ macro_rules! __pin_project_internal {
}
$proj_vis fn project_ref<'__pin>(
self: $crate::__private::Pin<&'__pin Self>,
- ) -> ProjectionRef<'__pin $(, $($lifetime,)* $($generics),* )?> {
+ ) -> ProjectionRef <'__pin, $($ty_generics)*> {
unsafe {
- let this = self.get_ref();
+ let Self { $($field),* } = self.get_ref();
ProjectionRef {
$(
- $field: $crate::__pin_project_internal!(@make_unsafe_field_proj
- this; $(#[$pin])? $field;
+ $field: $crate::__pin_project_internal!(@make_unsafe_field_proj;
+ $(#[$pin])? $field
)
),+
}
@@ -410,110 +283,25 @@ macro_rules! __pin_project_internal {
}
}
- // 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 ()>,
+ $crate::__pin_project_internal! { @make_unpin_impl;
+ [$vis $ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
$(
- $field: $crate::__pin_project_internal!(@make_unpin_bound
+ $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)?
- ),*
- )?
- {
+ $crate::__pin_project_internal! { @make_drop_impl;
+ [$ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
}
// 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
+ // #[forbid(safe_packed_borrows)] makes sure that doing this without
// an 'unsafe' block (which we deliberately do not generate)
// is a hard error.
//
@@ -523,50 +311,24 @@ macro_rules! __pin_project_internal {
// 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),* >)?
- )
+ #[forbid(safe_packed_borrows)]
+ fn __assert_not_repr_packed <$($impl_generics)*> (this: &$ident <$($ty_generics)*>)
$(where
- $( $where_clause_ty
- $(: $where_clause_bound)?
- $(: ?$where_clause_unsized_bound)?
- $(: $where_clause_lifetime_bound)?
- ),*
- )?
+ $($where_clause)*)?
{
$(
- &this.$field;
+ let _ = &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)?
- ),*
+ // =============================================================================================
+ // make_proj_ty: struct
+ (@make_proj_ty_struct;
+ [$proj_vis:vis]
+ [$vis:vis struct $ident:ident]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
{
$(
$(#[$pin:ident])?
@@ -577,157 +339,268 @@ macro_rules! __pin_project_internal {
#[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)?
- ),*
- )?>
+ $proj_vis struct Projection <'__pin, $($impl_generics)*>
where
- $ident $(< $($lifetime,)* $($generics),* >)?: '__pin,
- $( $where_clause_ty
- $(: $where_clause_bound)?
- $(: ?$where_clause_unsized_bound)?
- $(: $where_clause_lifetime_bound)?
- ),*
+ $ident <$($ty_generics)*>: '__pin
+ $(, $($where_clause)*)?
{
$(
- $field_vis $field: $crate::__pin_project_internal!(@make_proj_field
+ $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)?
- ),*
- )?>
+ $proj_vis struct ProjectionRef <'__pin, $($impl_generics)*>
where
- $ident $(< $($lifetime,)* $($generics),* >)?: '__pin,
- $( $where_clause_ty
- $(: $where_clause_bound)?
- $(: ?$where_clause_unsized_bound)?
- $(: $where_clause_lifetime_bound)?
- ),*
+ $ident <$($ty_generics)*>: '__pin
+ $(, $($where_clause)*)?
{
$(
- $field_vis $field: $crate::__pin_project_internal!(@make_proj_field
+ $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)?
- ),*
- >)?
+
+ // =============================================================================================
+ // make_unpin_impl
+ (@make_unpin_impl;
+ [$vis:vis $ident:ident]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+ $($field:tt)*
+ ) => {
+ // 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, $($impl_generics)*>
+ $(where
+ $($where_clause)*)?
{
- $(
- $(#[$pin:ident])?
- $field_vis:vis $field:ident: $field_ty:ty
- ),+
+ __dummy_lifetime: $crate::__private::PhantomData<&'__pin ()>,
+ $($field)*
}
- ) => {
- #[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)?
- ),*
- )?>
+ impl <'__pin, $($impl_generics)*> $crate::__private::Unpin for $ident <$($ty_generics)*>
where
- $ident $(< $($lifetime,)* $($generics),* >)?: '__pin,
+ __Origin <'__pin, $($ty_generics)*>: $crate::__private::Unpin
+ $(, $($where_clause)*)?
{
- $(
- $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,
+ };
+
+ // =============================================================================================
+ // make_drop_impl
+ (@make_drop_impl;
+ [$ident:ident]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+ ) => {
+ // 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, drop_bounds)]
+ impl<T: $crate::__private::Drop> MustNotImplDrop for T {}
+ impl <$($impl_generics)*> MustNotImplDrop for $ident <$($ty_generics)*>
+ $(where
+ $($where_clause)*)?
{
- $(
- $field_vis $field: $crate::__pin_project_internal!(@make_proj_field
- $(#[$pin])? $field_ty;
- )
- ),+
}
};
+ // =============================================================================================
// make_unpin_bound
- (@make_unpin_bound
+ (@make_unpin_bound;
#[pin]
$field_ty:ty
) => {
$field_ty
};
- (@make_unpin_bound
+ (@make_unpin_bound;
$field_ty:ty
) => {
$crate::__private::AlwaysUnpin<$field_ty>
};
+ // =============================================================================================
// make_unsafe_field_proj
- (@make_unsafe_field_proj
- $this:ident;
+ (@make_unsafe_field_proj;
#[pin]
- $field:ident;
- $($mut:ident)?
+ $field:ident
) => {
- $crate::__private::Pin::new_unchecked(&$($mut)? $this.$field)
+ $crate::__private::Pin::new_unchecked($field)
};
- (@make_unsafe_field_proj
- $this:ident;
- $field:ident;
- $($mut:ident)?
+ (@make_unsafe_field_proj;
+ $field:ident
) => {
- &$($mut)? $this.$field
+ $field
};
+ // =============================================================================================
// make_proj_field
- (@make_proj_field
+ (@make_proj_field;
#[pin]
$field_ty:ty;
$($mut:ident)?
) => {
$crate::__private::Pin<&'__pin $($mut)? ($field_ty)>
};
- (@make_proj_field
+ (@make_proj_field;
$field_ty:ty;
$($mut:ident)?
) => {
&'__pin $($mut)? ($field_ty)
};
- // limitation: no useful error messages (wontfix)
+ // =============================================================================================
+ // Parses input and determines 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! { @struct_internal;
+ [pub(crate)]
+ [$(#[$attrs])* pub struct $ident]
+ [$(<
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ $(= $generics_default)?
+ ),*
+ >)?]
+ [$(
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ ),*
+ )?]
+ [$( $( $lifetime ,)* $( $generics ),* )?]
+ [$(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! { @struct_internal;
+ [$vis]
+ [$(#[$attrs])* $vis struct $ident]
+ [$(<
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ $(= $generics_default)?
+ ),*
+ >)?]
+ [$(
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ ),*
+ )?]
+ [$( $( $lifetime ,)* $( $generics ),* )?]
+ [$(where $( $where_clause_ty
+ $(: $where_clause_bound)?
+ $(: ?$where_clause_unsized_bound)?
+ $(: $where_clause_lifetime_bound)?
+ ),* )?]
+ {
+ $(
+ $(#[$pin])?
+ $field_vis $field: $field_ty
+ ),+
+ }
+ }
+ };
}
// Not public API.
diff --git a/src/lib.rs.orig b/src/lib.rs.orig
new file mode 100644
index 0000000..0fef95e
--- /dev/null
+++ b/src/lib.rs.orig
@@ -0,0 +1,618 @@
+//! 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]
+//!
+//! [naming]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html
+//! [not-unpin]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unpin
+//! [pin-project]: https://github.com/taiki-e/pin-project
+//! [pinned-drop]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#pinned_drop
+//! [unsafe-unpin]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html#unsafeunpin
+
+#![no_std]
+#![doc(html_root_url = "https://docs.rs/pin-project-lite/0.1.11")]
+#![doc(test(
+ no_crate_inject,
+ attr(deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code))
+))]
+#![warn(unsafe_code)]
+#![warn(future_incompatible, rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
+#![warn(clippy::all, clippy::default_trait_access)]
+// mem::take and #[non_exhaustive] requires Rust 1.40, matches! requires Rust 1.42
+#![allow(
+ clippy::mem_replace_with_default,
+ clippy::manual_non_exhaustive,
+ clippy::match_like_matches_macro
+)]
+
+/// 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`].
+///
+/// ```rust
+/// use pin_project_lite::pin_project;
+/// use std::pin::Pin;
+///
+/// pin_project! {
+/// struct Struct<T> {
+/// #[pin]
+/// field: T,
+/// }
+/// }
+///
+/// impl<T> Struct<T> {
+/// fn call_project_twice(mut self: Pin<&mut Self>) {
+/// // `project` consumes `self`, so reborrow the `Pin<&mut Self>` via `as_mut`.
+/// self.as_mut().project();
+/// self.as_mut().project();
+/// }
+/// }
+/// ```
+///
+/// # `!Unpin`
+///
+/// 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] // <------ This `#[pin]` is required to make `Struct` to `!Unpin`.
+/// _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. (wontfix)
+// * no support for overlapping lifetime names. (wontfix)
+// * no interoperability with other field attributes.
+// * no useful error messages. (wontfix)
+// etc...
+
+// Not public API.
+#[doc(hidden)]
+#[macro_export]
+macro_rules! __pin_project_internal {
+ // =============================================================================================
+ // main: struct
+ (@struct_internal;
+ [$proj_vis:vis]
+ [$(#[$attrs:meta])* $vis:vis struct $ident:ident]
+ [$($def_generics:tt)*]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
+ {
+ $(
+ $(#[$pin:ident])?
+ $field_vis:vis $field:ident: $field_ty:ty
+ ),+
+ }
+ ) => {
+ $(#[$attrs])*
+ $vis struct $ident $($def_generics)*
+ $(where
+ $($where_clause)*)?
+ {
+ $(
+ $field_vis $field: $field_ty
+ ),+
+ }
+
+ #[allow(explicit_outlives_requirements)]
+ #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
+ #[allow(clippy::redundant_pub_crate)]
+ #[allow(clippy::used_underscore_binding)]
+ const _: () = {
+ $crate::__pin_project_internal! { @make_proj_ty_struct;
+ [$proj_vis]
+ [$vis struct $ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ {
+ $(
+ $(#[$pin])?
+ $field_vis $field: $field_ty
+ ),+
+ }
+ }
+
+ impl <$($impl_generics)*> $ident <$($ty_generics)*>
+ $(where
+ $($where_clause)*)?
+ {
+ $proj_vis fn project<'__pin>(
+ self: $crate::__private::Pin<&'__pin mut Self>,
+ ) -> Projection <'__pin, $($ty_generics)*> {
+ unsafe {
+ let Self { $($field),* } = self.get_unchecked_mut();
+ Projection {
+ $(
+ $field: $crate::__pin_project_internal!(@make_unsafe_field_proj;
+ $(#[$pin])? $field
+ )
+ ),+
+ }
+ }
+ }
+ $proj_vis fn project_ref<'__pin>(
+ self: $crate::__private::Pin<&'__pin Self>,
+ ) -> ProjectionRef <'__pin, $($ty_generics)*> {
+ unsafe {
+ let Self { $($field),* } = self.get_ref();
+ ProjectionRef {
+ $(
+ $field: $crate::__pin_project_internal!(@make_unsafe_field_proj;
+ $(#[$pin])? $field
+ )
+ ),+
+ }
+ }
+ }
+ }
+
+ $crate::__pin_project_internal! { @make_unpin_impl;
+ [$vis $ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ $(
+ $field: $crate::__pin_project_internal!(@make_unpin_bound;
+ $(#[$pin])? $field_ty
+ )
+ ),+
+ }
+
+ $crate::__pin_project_internal! { @make_drop_impl;
+ [$ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ }
+
+ // 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
+ // #[forbid(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.
+ #[forbid(safe_packed_borrows)]
+ fn __assert_not_repr_packed <$($impl_generics)*> (this: &$ident <$($ty_generics)*>)
+ $(where
+ $($where_clause)*)?
+ {
+ $(
+ let _ = &this.$field;
+ )+
+ }
+ };
+ };
+
+ // =============================================================================================
+ // make_proj_ty: struct
+ (@make_proj_ty_struct;
+ [$proj_vis:vis]
+ [$vis:vis struct $ident:ident]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+ {
+ $(
+ $(#[$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, $($impl_generics)*>
+ where
+ $ident <$($ty_generics)*>: '__pin
+ $(, $($where_clause)*)?
+ {
+ $(
+ $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, $($impl_generics)*>
+ where
+ $ident <$($ty_generics)*>: '__pin
+ $(, $($where_clause)*)?
+ {
+ $(
+ $field_vis $field: $crate::__pin_project_internal!(@make_proj_field;
+ $(#[$pin])? $field_ty;
+ )
+ ),+
+ }
+ };
+
+ // =============================================================================================
+ // make_unpin_impl
+ (@make_unpin_impl;
+ [$vis:vis $ident:ident]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+ $($field:tt)*
+ ) => {
+ // 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, $($impl_generics)*>
+ $(where
+ $($where_clause)*)?
+ {
+ __dummy_lifetime: $crate::__private::PhantomData<&'__pin ()>,
+ $($field)*
+ }
+ impl <'__pin, $($impl_generics)*> $crate::__private::Unpin for $ident <$($ty_generics)*>
+ where
+ __Origin <'__pin, $($ty_generics)*>: $crate::__private::Unpin
+ $(, $($where_clause)*)?
+ {
+ }
+ };
+
+ // =============================================================================================
+ // make_drop_impl
+ (@make_drop_impl;
+ [$ident:ident]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+ ) => {
+ // 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, drop_bounds)]
+ impl<T: $crate::__private::Drop> MustNotImplDrop for T {}
+ impl <$($impl_generics)*> MustNotImplDrop for $ident <$($ty_generics)*>
+ $(where
+ $($where_clause)*)?
+ {
+ }
+ };
+
+ // =============================================================================================
+ // 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;
+ #[pin]
+ $field:ident
+ ) => {
+ $crate::__private::Pin::new_unchecked($field)
+ };
+ (@make_unsafe_field_proj;
+ $field:ident
+ ) => {
+ $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)
+ };
+
+ // =============================================================================================
+ // Parses input and determines 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! { @struct_internal;
+ [pub(crate)]
+ [$(#[$attrs])* pub struct $ident]
+ [$(<
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ $(= $generics_default)?
+ ),*
+ >)?]
+ [$(
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ ),*
+ )?]
+ [$( $( $lifetime ,)* $( $generics ),* )?]
+ [$(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! { @struct_internal;
+ [$vis]
+ [$(#[$attrs])* $vis struct $ident]
+ [$(<
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ $(= $generics_default)?
+ ),*
+ >)?]
+ [$(
+ $( $lifetime $(: $lifetime_bound)? ,)*
+ $( $generics
+ $(: $generics_bound)?
+ $(: ?$generics_unsized_bound)?
+ $(: $generics_lifetime_bound)?
+ ),*
+ )?]
+ [$( $( $lifetime ,)* $( $generics ),* )?]
+ [$(where $( $where_clause_ty
+ $(: $where_clause_bound)?
+ $(: ?$where_clause_unsized_bound)?
+ $(: $where_clause_lifetime_bound)?
+ ),* )?]
+ {
+ $(
+ $(#[$pin])?
+ $field_vis $field: $field_ty
+ ),+
+ }
+ }
+ };
+}
+
+// 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/auxiliary/mod.rs b/tests/auxiliary/mod.rs
new file mode 100644
index 0000000..1457099
--- /dev/null
+++ b/tests/auxiliary/mod.rs
@@ -0,0 +1,12 @@
+#![allow(dead_code, unused_macros)]
+
+macro_rules! assert_unpin {
+ ($ty:ty) => {
+ static_assertions::assert_impl_all!($ty: Unpin);
+ };
+}
+macro_rules! assert_not_unpin {
+ ($ty:ty) => {
+ static_assertions::assert_not_impl_all!($ty: Unpin);
+ };
+}
diff --git a/tests/lint.rs b/tests/lint.rs
index 24491bb..e81a13c 100644
--- a/tests/lint.rs
+++ b/tests/lint.rs
@@ -1,34 +1,26 @@
-#![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,
+#![warn(nonstandard_style, rust_2018_idioms, rustdoc, unused)]
+// Note: This does not guarantee compatibility with forbidding these lints in the future.
+// If rustc adds a new lint, we may not be able to keep this.
+#![forbid(future_incompatible, rust_2018_compatibility)]
+#![allow(unknown_lints)] // for old compilers
+#![warn(
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,
@@ -36,37 +28,101 @@
unused_results,
variant_size_differences
)]
-// unused_crate_dependencies: unrelated
-// unsafe_code: checked in forbid_unsafe module
+// absolute_paths_not_starting_with_crate, anonymous_parameters, keyword_idents, pointer_structural_match: forbidden as a part of future_incompatible
+// missing_doc_code_examples, private_doc_tests, invalid_html_tags: warned as a part of rustdoc
// unsafe_block_in_unsafe_fn: unstable
+// unsafe_code: forbidden
+// unstable_features: deprecated: https://doc.rust-lang.org/beta/rustc/lints/listing/allowed-by-default.html#unstable-features
+// unused_crate_dependencies: unrelated
+#![warn(clippy::all, clippy::pedantic, clippy::nursery)]
+#![warn(clippy::restriction)]
+#![allow(clippy::blanket_clippy_restriction_lints)] // this is a test, so enable all restriction lints intentionally.
+
+// Check interoperability with rustc and clippy lints.
+
pub mod basic {
include!("include/basic.rs");
}
-pub mod clippy {
+pub mod box_pointers {
use pin_project_lite::pin_project;
pin_project! {
- pub struct MutMut<'a, T, U> {
+ #[derive(Debug)]
+ pub struct Struct {
+ #[pin]
+ pub p: Box<isize>,
+ pub u: Box<isize>,
+ }
+ }
+}
+
+pub mod explicit_outlives_requirements {
+ use pin_project_lite::pin_project;
+
+ pin_project! {
+ #[derive(Debug)]
+ pub struct Struct<'a, T, U>
+ where
+ T: ?Sized,
+ U: ?Sized,
+ {
#[pin]
pub pinned: &'a mut T,
pub unpinned: &'a mut U,
}
}
+}
+
+pub mod clippy_mut_mut {
+ use pin_project_lite::pin_project;
pin_project! {
- pub struct TypeRepetitionInBoundsStruct<T, U>
+ #[derive(Debug)]
+ pub struct Struct<'a, T, U> {
+ #[pin]
+ pub pinned: &'a mut T,
+ pub unpinned: &'a mut U,
+ }
+ }
+}
+
+#[allow(unreachable_pub)]
+mod clippy_redundant_pub_crate {
+ use pin_project_lite::pin_project;
+
+ pin_project! {
+ #[derive(Debug)]
+ pub struct Struct<T, U> {
+ #[pin]
+ pub pinned: T,
+ pub unpinned: U,
+ }
+ }
+}
+
+pub mod clippy_type_repetition_in_bounds {
+ use pin_project_lite::pin_project;
+
+ pin_project! {
+ #[derive(Debug)]
+ pub struct Struct<T, U>
where
- TypeRepetitionInBoundsStruct<T, U>: Sized,
+ Struct<T, U>: Sized,
{
#[pin]
pub pinned: T,
pub unpinned: U,
}
}
+}
+
+pub mod clippy_used_underscore_binding {
+ use pin_project_lite::pin_project;
pin_project! {
- pub struct UsedUnderscoreBindingStruct<T, U> {
+ #[derive(Debug)]
+ pub struct Struct<T, U> {
#[pin]
pub _pinned: T,
pub _unpinned: U,
@@ -74,17 +130,41 @@ pub mod clippy {
}
}
+#[allow(box_pointers)]
+#[allow(clippy::restriction)]
#[rustversion::attr(not(nightly), ignore)]
#[test]
fn check_lint_list() {
- use std::{env, process::Command};
+ use std::{env, fs, path::PathBuf, process::Command, str};
- (|| -> 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);
+ type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
+
+ fn assert_eq(expected_path: &str, actual: &str) -> Result<()> {
+ let manifest_dir = env::var_os("CARGO_MANIFEST_DIR")
+ .map(PathBuf::from)
+ .expect("CARGO_MANIFEST_DIR not set");
+ let expected_path = manifest_dir.join(expected_path);
+ let expected = fs::read_to_string(&expected_path)?;
+ if expected != actual {
+ if env::var_os("CI").map_or(false, |v| v == "true") {
+ panic!(
+ "assertion failed:\n\nEXPECTED:\n{0}\n{1}\n{0}\n\nACTUAL:\n{0}\n{2}\n{0}\n",
+ "-".repeat(60),
+ expected,
+ actual,
+ );
+ } else {
+ fs::write(&expected_path, actual)?;
+ }
+ }
Ok(())
+ }
+
+ (|| -> Result<()> {
+ let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
+ let output = Command::new(rustc).args(&["-W", "help"]).output()?;
+ let new = str::from_utf8(&output.stdout)?;
+ assert_eq("tests/lint.txt", new)
})()
.unwrap_or_else(|e| panic!("{}", e));
}
diff --git a/tests/lint.txt b/tests/lint.txt
index 8de71e0..e4c9f98 100644
--- a/tests/lint.txt
+++ b/tests/lint.txt
@@ -13,11 +13,10 @@ Lint checks provided by rustc:
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
+ invalid-html-tags allow detects invalid HTML tags in doc comments
keyword-idents allow detects edition keywords being used as an identifier
macro-use-extern-crate allow the `#[macro_use]` attribute is now deprecated in favor of using macros via the module system
meta-variable-misuse allow possible meta-variable misuse at macro definition
@@ -27,6 +26,7 @@ Lint checks provided by rustc:
missing-docs allow detects missing documentation for public members
missing-doc-code-examples allow detects publicly-exported items without code samples in their documentation
non-ascii-idents allow detects non-ASCII identifiers
+ pointer-structural-match allow pointers are not structural-match
private-doc-tests allow detects code samples in docs of private items not documented by rustdoc
single-use-lifetimes allow detects lifetime parameters that are only used once
trivial-casts allow detects trivial casts which could be removed
@@ -47,21 +47,31 @@ Lint checks provided by rustc:
asm-sub-register warn using only a subset of a register for inline asm inputs
bare-trait-objects warn suggest using `dyn Trait` for trait objects
bindings-with-variant-name warn detects pattern bindings with the same name as one of the matched variants
+ broken-intra-doc-links warn failures in resolving intra-doc link targets
+ cenum-impl-drop-cast warn a C-like enum implementing Drop is cast
+ clashing-extern-declarations warn detects when an extern fn has been declared with the same name but different types
coherence-leak-check warn distinct impls distinguished only by the leak-check code
+ confusable-idents warn detects visually confusable pairs between identifiers
+ const-evaluatable-unchecked warn detects a generic constant is used in a type without a emitting a warning
+ const-item-mutation warn detects attempts to mutate a `const` item
dead-code warn detect unused, unexported items
deprecated warn detects use of deprecated items
+ drop-bounds warn bounds of the form `T: Drop` are useless
ellipsis-inclusive-range-patterns warn `...` range patterns are deprecated
exported-private-dependencies warn public interface leaks type from a private dependency
illegal-floating-point-literal-pattern warn floating-point literals cannot be used in patterns
improper-ctypes warn proper use of libc types in foreign modules
+ improper-ctypes-definitions warn proper use of libc types in foreign item definitions
incomplete-features warn incomplete features that may function improperly in some or all cases
+ indirect-structural-match warn constant used in pattern contains value of non-structural-match type in a field or a variant
inline-no-sanitize warn detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]`
- 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-codeblock-attributes warn codeblock attribute looks a lot like a known one
invalid-value warn an invalid value is being created (such as a NULL reference)
irrefutable-let-patterns warn detects irrefutable patterns in if-let and while-let statements
late-bound-lifetime-arguments warn detects generic lifetime arguments in path segments with late bound lifetime parameters
+ mixed-script-confusables warn detects Unicode scripts whose mixed script confusables codepoints are solely used
mutable-borrow-reservation-conflict warn reservation of a two-phased borrow conflicts with other shared borrows
+ nontrivial-structural-match warn constant used in pattern of non-structural-match type and the constant's initializer expression contains values of non-structural-match types
non-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
@@ -108,9 +118,9 @@ Lint checks provided by rustc:
conflicting-repr-hints deny conflicts between `#[repr(..)]` hints that were previously accepted and used in practice
const-err deny constant evaluation detected erroneous expression
ill-formed-attribute-input deny ill-formed attribute inputs that were previously accepted and used in practice
+ incomplete-include deny trailing content in included file
invalid-type-param-default deny type parameter default erroneously allowed in invalid location
macro-expanded-macro-exports-accessed-by-absolute-paths deny macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
- missing-fragment-specifier deny detects missing fragment specifiers in unused `macro_rules!` patterns
mutable-transmutes deny mutating transmuted &mut T from &T may cause undefined behavior
no-mangle-const-items deny const items will not have their symbols exported
order-dependent-trait-objects deny trait-object types were treated as different depending on marker-trait order
@@ -127,11 +137,11 @@ 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
+ 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, late-bound-lifetime-arguments, order-dependent-trait-objects, coherence-leak-check, tyvar-behind-raw-pointer, absolute-paths-not-starting-with-crate, unstable-name-collisions, where-clauses-object-safety, proc-macro-derive-resolution-fallback, macro-expanded-macro-exports-accessed-by-absolute-paths, ill-formed-attribute-input, conflicting-repr-hints, ambiguous-associated-items, mutable-borrow-reservation-conflict, indirect-structural-match, pointer-structural-match, nontrivial-structural-match, soft-unstable, cenum-impl-drop-cast, const-evaluatable-unchecked, 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
+ rustdoc broken-intra-doc-links, private-intra-doc-links, invalid-codeblock-attributes, missing-doc-code-examples, private-doc-tests, invalid-html-tags
unused unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, 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
diff --git a/tests/proper_unpin.rs b/tests/proper_unpin.rs
new file mode 100644
index 0000000..bbee78c
--- /dev/null
+++ b/tests/proper_unpin.rs
@@ -0,0 +1,49 @@
+#![warn(rust_2018_idioms, single_use_lifetimes)]
+#![allow(dead_code)]
+
+#[macro_use]
+mod auxiliary;
+
+pub mod default {
+ use pin_project_lite::pin_project;
+ use std::marker::PhantomPinned;
+
+ struct Inner<T> {
+ f: T,
+ }
+
+ assert_unpin!(Inner<()>);
+ assert_not_unpin!(Inner<PhantomPinned>);
+
+ pin_project! {
+ struct Foo<T, U> {
+ #[pin]
+ f1: Inner<T>,
+ f2: U,
+ }
+ }
+
+ assert_unpin!(Foo<(), ()>);
+ assert_unpin!(Foo<(), PhantomPinned>);
+ assert_not_unpin!(Foo<PhantomPinned, ()>);
+ assert_not_unpin!(Foo<PhantomPinned, PhantomPinned>);
+
+ pin_project! {
+ struct TrivialBounds {
+ #[pin]
+ f: PhantomPinned,
+ }
+ }
+
+ assert_not_unpin!(TrivialBounds);
+
+ pin_project! {
+ struct Bar<'a, T, U> {
+ #[pin]
+ f1: &'a mut Inner<T>,
+ f2: U,
+ }
+ }
+
+ assert_unpin!(Bar<'_, PhantomPinned, PhantomPinned>);
+}
diff --git a/tests/test.rs b/tests/test.rs
index 06ec259..1af2b59 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,7 +1,9 @@
-#![no_std]
#![warn(rust_2018_idioms, single_use_lifetimes)]
#![allow(dead_code)]
+#[macro_use]
+mod auxiliary;
+
use core::{marker::PhantomPinned, pin::Pin};
use pin_project_lite::pin_project;
@@ -10,30 +12,30 @@ fn projection() {
pin_project! {
struct Struct<T, U> {
#[pin]
- field1: T,
- field2: U,
+ f1: T,
+ f2: U,
}
}
- let mut s = Struct { field1: 1, field2: 2 };
+ let mut s = Struct { f1: 1, f2: 2 };
let mut s_orig = Pin::new(&mut s);
let s = s_orig.as_mut().project();
- let x: Pin<&mut i32> = s.field1;
+ let x: Pin<&mut i32> = s.f1;
assert_eq!(*x, 1);
- let y: &mut i32 = s.field2;
+ let y: &mut i32 = s.f2;
assert_eq!(*y, 2);
- assert_eq!(s_orig.as_ref().field1, 1);
- assert_eq!(s_orig.as_ref().field2, 2);
+ assert_eq!(s_orig.as_ref().f1, 1);
+ assert_eq!(s_orig.as_ref().f2, 2);
- let mut s = Struct { field1: 1, field2: 2 };
+ let mut s = Struct { f1: 1, f2: 2 };
let s = Pin::new(&mut s).project();
- let _: Pin<&mut i32> = s.field1;
- let _: &mut i32 = s.field2;
+ let _: Pin<&mut i32> = s.f1;
+ let _: &mut i32 = s.f2;
}
#[test]
@@ -43,7 +45,7 @@ fn where_clause() {
where
T: Copy,
{
- field: T,
+ f: T,
}
}
}
@@ -56,8 +58,8 @@ fn where_clause_and_associated_type_field() {
I: Iterator,
{
#[pin]
- field1: I,
- field2: I::Item,
+ f1: I,
+ f2: I::Item,
}
}
@@ -67,8 +69,8 @@ fn where_clause_and_associated_type_field() {
I: Iterator<Item = J>,
{
#[pin]
- field1: I,
- field2: J,
+ f1: I,
+ f2: J,
}
}
@@ -77,7 +79,7 @@ fn where_clause_and_associated_type_field() {
where
T: 'static,
{
- field: T,
+ f: T,
}
}
@@ -91,7 +93,7 @@ fn derive_copy() {
pin_project! {
#[derive(Clone, Copy)]
struct Struct<T> {
- val: T,
+ f: T,
}
}
@@ -106,57 +108,57 @@ fn move_out() {
pin_project! {
struct Struct {
- val: NotCopy,
+ f: NotCopy,
}
}
- let x = Struct { val: NotCopy };
- let _val: NotCopy = x.val;
+ let x = Struct { f: NotCopy };
+ let _val: NotCopy = x.f;
}
#[test]
fn trait_bounds_on_type_generics() {
pin_project! {
pub struct Struct1<'a, T: ?Sized> {
- field: &'a mut T,
+ f: &'a mut T,
}
}
pin_project! {
pub struct Struct2<'a, T: ::core::fmt::Debug> {
- field: &'a mut T,
+ f: &'a mut T,
}
}
pin_project! {
pub struct Struct3<'a, T: core::fmt::Debug> {
- field: &'a mut T,
+ f: &'a mut T,
}
}
// pin_project! {
// pub struct Struct4<'a, T: core::fmt::Debug + core::fmt::Display> {
- // field: &'a mut T,
+ // f: &'a mut T,
// }
// }
// pin_project! {
// pub struct Struct5<'a, T: core::fmt::Debug + ?Sized> {
- // field: &'a mut T,
+ // f: &'a mut T,
// }
// }
pin_project! {
pub struct Struct6<'a, T: core::fmt::Debug = [u8; 16]> {
- field: &'a mut T,
+ f: &'a mut T,
}
}
- let _: Struct6<'_> = Struct6 { field: &mut [0u8; 16] };
+ let _: Struct6<'_> = Struct6 { f: &mut [0u8; 16] };
pin_project! {
pub struct Struct7<T: 'static> {
- field: T,
+ f: T,
}
}
@@ -166,8 +168,8 @@ fn trait_bounds_on_type_generics() {
pin_project! {
pub struct Struct8<'a, 'b: 'a> {
- field1: &'a u8,
- field2: &'b u8,
+ f1: &'a u8,
+ f2: &'b u8,
}
}
}
@@ -184,6 +186,7 @@ fn private_type_in_public_type() {
struct PrivateStruct<T>(T);
}
+#[allow(clippy::needless_lifetimes)]
#[test]
fn lifetime_project() {
pin_project! {
@@ -209,50 +212,25 @@ fn lifetime_project() {
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> {
+ fn get_pin_ref_elided(self: Pin<&Self>) -> Pin<&T> {
self.project_ref().pinned
}
- fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut &'b mut T> {
+ fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&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> {
+ 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(self: Pin<&mut Self>) -> Pin<&mut T> {
+ fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut &'b mut T> {
self.project().pinned
}
- }
-
- impl<'b, T, U> Struct2<'b, T, U> {
- fn get_pin_ref(self: Pin<&Self>) -> Pin<&&'b mut T> {
+ fn get_pin_ref_elided(self: Pin<&Self>) -> Pin<&&'b mut T> {
self.project_ref().pinned
}
- fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut &'b mut T> {
+ fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut &'b mut T> {
self.project().pinned
}
}
@@ -262,20 +240,20 @@ mod visibility {
use pin_project_lite::pin_project;
pin_project! {
- pub(crate) struct A {
- pub b: u8,
+ pub(crate) struct S {
+ pub f: u8,
}
}
}
#[test]
fn visibility() {
- let mut x = visibility::A { b: 0 };
+ let mut x = visibility::S { f: 0 };
let x = Pin::new(&mut x);
let y = x.as_ref().project_ref();
- let _: &u8 = y.b;
+ let _: &u8 = y.f;
let y = x.project();
- let _: &mut u8 = y.b;
+ let _: &mut u8 = y.f;
}
#[test]
@@ -283,44 +261,42 @@ fn trivial_bounds() {
pin_project! {
pub struct NoGenerics {
#[pin]
- field: PhantomPinned,
+ f: PhantomPinned,
}
}
+
+ assert_not_unpin!(NoGenerics);
}
#[test]
fn dst() {
pin_project! {
pub struct Struct1<T: ?Sized> {
- x: T,
+ f: T,
}
}
- let mut x = Struct1 { x: 0_u8 };
+ let mut x = Struct1 { f: 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;
+ let _y: &mut (dyn core::fmt::Debug) = x.project().f;
pin_project! {
pub struct Struct2<T: ?Sized> {
#[pin]
- x: T,
+ f: T,
}
}
- let mut x = Struct2 { x: 0_u8 };
+ let mut x = Struct2 { f: 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;
-}
+ let _y: Pin<&mut (dyn core::fmt::Debug + Unpin)> = x.project().f;
-#[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,
+ f: T,
}
}
@@ -330,7 +306,14 @@ fn unsized_in_where_clause() {
T: ?Sized,
{
#[pin]
- x: T,
+ f: T,
+ }
+ }
+
+ pin_project! {
+ struct Struct11<'a, T: ?Sized, U: ?Sized> {
+ f1: &'a mut T,
+ f2: U,
}
}
}
@@ -366,19 +349,67 @@ fn dyn_type() {
#[test]
fn no_infer_outlives() {
- trait Bar<X> {
+ trait Trait<X> {
type Y;
}
- struct Example<A>(A);
+ struct Struct1<A>(A);
- impl<X, T> Bar<X> for Example<T> {
+ impl<X, T> Trait<X> for Struct1<T> {
type Y = Option<T>;
}
pin_project! {
- struct Foo<A, B> {
- _x: <Example<A> as Bar<B>>::Y,
+ struct Struct2<A, B> {
+ _f: <Struct1<A> as Trait<B>>::Y,
+ }
+ }
+}
+
+// https://github.com/taiki-e/pin-project-lite/issues/31
+#[test]
+fn trailing_comma() {
+ pub trait T {}
+
+ pin_project! {
+ pub struct S1<
+ A: T,
+ B: T,
+ > {
+ f: (A, B),
}
}
+
+ pin_project! {
+ pub struct S2<
+ A,
+ B,
+ >
+ where
+ A: T,
+ B: T,
+ {
+ f: (A, B),
+ }
+ }
+
+ pin_project! {
+ #[allow(explicit_outlives_requirements)]
+ pub struct S3<
+ 'a,
+ A: 'a,
+ B: 'a,
+ > {
+ f: &'a (A, B),
+ }
+ }
+
+ // pin_project! {
+ // pub struct S4<
+ // 'a,
+ // 'b: 'a, // <-----
+ // > {
+ // f: &'a &'b (),
+ // }
+ // }
}
diff --git a/tests/ui/overlapping_unpin_struct.stderr b/tests/ui/overlapping_unpin_struct.stderr
index b944b0f..ab76f81 100644
--- a/tests/ui/overlapping_unpin_struct.stderr
+++ b/tests/ui/overlapping_unpin_struct.stderr
@@ -1,11 +1,11 @@
-error[E0277]: `std::marker::PhantomPinned` cannot be unpinned
+error[E0277]: `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`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `_::__Origin<'_, PhantomPinned>`, the trait `Unpin` is not implemented for `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>`
+ = note: required because it appears within the type `_::__Origin<'_, PhantomPinned>`
+ = note: required because of the requirements on the impl of `Unpin` for `Foo<PhantomPinned>`
diff --git a/tests/ui/proper_unpin.rs b/tests/ui/proper_unpin.rs
deleted file mode 100644
index 3c85f2d..0000000
--- a/tests/ui/proper_unpin.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-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
deleted file mode 100644
index 8149918..0000000
--- a/tests/ui/proper_unpin.stderr
+++ /dev/null
@@ -1,37 +0,0 @@
-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.stderr b/tests/ui/unpin_sneaky.stderr
index 77ad2dc..39a7745 100644
--- a/tests/ui/unpin_sneaky.stderr
+++ b/tests/ui/unpin_sneaky.stderr
@@ -4,7 +4,7 @@ error[E0412]: cannot find type `__Origin` in this scope
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]`
+error[E0321]: cross-crate traits with a default impl, like `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