aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaibo Huang <hhb@google.com>2021-01-06 17:30:19 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-01-06 17:30:19 +0000
commita0285f0c7c38adc4afbf54bc7b1d068df5816062 (patch)
treeeb1c29b66745b559ef29b60e31ab531c4762a3ad
parentea6c4b4143ebdcaa3675a08568d8383186c21cc6 (diff)
parent5e8019875e932d96b62580cca9af02e8bb8d10af (diff)
downloadpin-project-lite-a0285f0c7c38adc4afbf54bc7b1d068df5816062.tar.gz
Upgrade rust/crates/pin-project-lite to 0.2.1 am: 78dfce4e2b am: 5e8019875e
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/pin-project-lite/+/1540750 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: Idbfa7b901ef9cefd5bf2e0fd97287c8614320e9f
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--.clippy.toml1
-rw-r--r--.editorconfig9
-rw-r--r--.gitattributes3
-rw-r--r--.github/CODEOWNERS1
-rw-r--r--.github/bors.toml2
-rw-r--r--.github/workflows/ci.yml124
-rw-r--r--.rustfmt.toml (renamed from rustfmt.toml)9
-rw-r--r--CHANGELOG.md97
-rw-r--r--CODE_OF_CONDUCT.md9
-rw-r--r--Cargo.toml6
-rw-r--r--Cargo.toml.orig6
-rw-r--r--METADATA10
-rw-r--r--README.md93
-rwxr-xr-xci/install-component.sh27
-rwxr-xr-xci/install-rust.sh12
-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.rs807
-rw-r--r--src/lib.rs.orig807
-rw-r--r--tests/auxiliary/mod.rs2
-rw-r--r--tests/compiletest.rs8
-rw-r--r--tests/include/basic.rs25
-rw-r--r--tests/lint.rs142
-rw-r--r--tests/lint.txt148
-rw-r--r--tests/proper_unpin.rs31
-rw-r--r--tests/test.rs215
-rw-r--r--tests/ui/invalid-bounds.stderr90
-rw-r--r--tests/ui/invalid.stderr31
-rw-r--r--tests/ui/overlapping_lifetime_names.stderr4
-rw-r--r--tests/ui/unsupported.stderr64
33 files changed, 2122 insertions, 796 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index dff72dd..f892109 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
{
"git": {
- "sha1": "afa54fe19f0a7629b874fb7d4b825e806596ef10"
+ "sha1": "f1a711f00677639a51118cc4f31ea4ec59220f0e"
}
}
diff --git a/.clippy.toml b/.clippy.toml
new file mode 100644
index 0000000..983eb57
--- /dev/null
+++ b/.clippy.toml
@@ -0,0 +1 @@
+msrv = "1.37"
diff --git a/.editorconfig b/.editorconfig
index 933a9a4..a73a88d 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,19 +1,20 @@
# EditorConfig configuration
# https://editorconfig.org
-# Top-most EditorConfig file
root = true
[*]
+charset = utf-8
end_of_line = lf
+indent_size = 4
+indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
-charset = utf-8
-indent_style = space
-indent_size = 4
[*.{json,yml,md}]
indent_size = 2
[*.sh]
+indent_size = 2
+binary_next_line = true
switch_case_indent = true
diff --git a/.gitattributes b/.gitattributes
index 45bca84..6313b56 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,4 +1 @@
-[attr]rust text eol=lf whitespace=tab-in-indent,trailing-space,tabwidth=4
-
* text=auto eol=lf
-*.rs rust
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
deleted file mode 100644
index 2fdc28f..0000000
--- a/.github/CODEOWNERS
+++ /dev/null
@@ -1 +0,0 @@
-* @taiki-e
diff --git a/.github/bors.toml b/.github/bors.toml
deleted file mode 100644
index 1779788..0000000
--- a/.github/bors.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-status = ["ci"]
-delete_merged_branches = true
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
deleted file mode 100644
index aa2394e..0000000
--- a/.github/workflows/ci.yml
+++ /dev/null
@@ -1,124 +0,0 @@
-name: CI
-
-on:
- pull_request:
- push:
- branches:
- - master
- - staging
- schedule:
- - cron: '0 1 * * *'
-
-env:
- RUSTFLAGS: -Dwarnings
- RUST_BACKTRACE: 1
-
-defaults:
- run:
- shell: bash
-
-jobs:
- test:
- name: test
- strategy:
- matrix:
- rust:
- # This is the minimum supported Rust version of this crate.
- # When updating this, the reminder to update the minimum supported Rust version in README.md.
- - 1.37.0
- - stable
- - beta
- - nightly
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Install Rust
- run: ci/install-rust.sh ${{ matrix.rust }}
- - 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 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 and Rustfmt
- run: ci/install-component.sh rustfmt
- - run: cargo fmt --all -- --check
-
- rustdoc:
- name: rustdoc
- env:
- RUSTDOCFLAGS: -Dwarnings
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Install Rust
- run: ci/install-rust.sh
- - 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
- # successful listening to webhooks only.
- #
- # ALL THE PREVIOUS JOBS NEEDS TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
-
- ci-success:
- name: ci
- if: github.event_name == 'push' && success()
- needs:
- - test
- - expandtest
- - clippy
- - rustfmt
- - rustdoc
- - shellcheck
- runs-on: ubuntu-latest
- steps:
- - name: Mark the job as a success
- run: exit 0
- ci-failure:
- name: ci
- if: github.event_name == 'push' && !success()
- needs:
- - test
- - expandtest
- - clippy
- - rustfmt
- - rustdoc
- - shellcheck
- runs-on: ubuntu-latest
- steps:
- - name: Mark the job as a failure
- run: exit 1
diff --git a/rustfmt.toml b/.rustfmt.toml
index 18c6d2a..6604f5c 100644
--- a/rustfmt.toml
+++ b/.rustfmt.toml
@@ -1,10 +1,11 @@
# Rustfmt configuration
-# https://github.com/rust-lang/rustfmt/blob/master/Configurations.md
+# https://github.com/rust-lang/rustfmt/blob/HEAD/Configurations.md
# This is required for bug-fixes, which technically can't be made to the stable
# first version.
# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3383).
version = "Two"
+# Rustfmt cannot format long lines inside macros, but this option detects this.
# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3391)
error_on_line_overflow = true
@@ -21,7 +22,13 @@ merge_imports = true
# This is unstable (tracking issue: https://github.com/rust-lang/rustfmt/issues/3348).
format_code_in_doc_comments = true
+# Automatically fix deprecated style.
+use_field_init_shorthand = true
+use_try_shorthand = true
+
# Set the default settings again to always apply the proper formatting without
# being affected by the editor settings.
edition = "2018"
+hard_tabs = false
+newline_style = "Unix"
tab_spaces = 4
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8c8087f..fc1b7d1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,77 +4,138 @@ All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org).
+<!--
+Note: In this file, do not use the hard wrap in the middle of a sentence for compatibility with GitHub comment style markdown rendering.
+-->
+
## [Unreleased]
+## [0.2.1] - 2021-01-05
+
+- Exclude unneeded files from crates.io.
+
+## [0.2.0] - 2020-11-13
+
+- [`pin_project!` macro now supports enums.][28]
+
+ To use `pin_project!` on enums, you need to name the projection type returned from the method.
+
+ ```rust
+ use pin_project_lite::pin_project;
+ use std::pin::Pin;
+
+ pin_project! {
+ #[project = EnumProj]
+ enum Enum<T, U> {
+ Variant { #[pin] pinned: T, unpinned: U },
+ }
+ }
+
+ impl<T, U> Enum<T, U> {
+ fn method(self: Pin<&mut Self>) {
+ match self.project() {
+ EnumProj::Variant { pinned, unpinned } => {
+ let _: Pin<&mut T> = pinned;
+ let _: &mut U = unpinned;
+ }
+ }
+ }
+ }
+ ```
+
+- [Support naming the projection types.][28]
+
+ By passing an attribute with the same name as the method, you can name the projection type returned from the method:
+
+ ```rust
+ use pin_project_lite::pin_project;
+ use std::pin::Pin;
+
+ pin_project! {
+ #[project = StructProj]
+ struct Struct<T> {
+ #[pin]
+ field: T,
+ }
+ }
+
+ fn func<T>(x: Pin<&mut Struct<T>>) {
+ let StructProj { field } = x.project();
+ let _: Pin<&mut T> = field;
+ }
+ ```
+
+[28]: https://github.com/taiki-e/pin-project-lite/pull/28
+
## [0.1.11] - 2020-10-20
-* Suppress `clippy::redundant_pub_crate` lint in generated code.
+- Suppress `clippy::redundant_pub_crate` lint in generated code.
-* Documentation improvements.
+- 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.
+- 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
+- Fix trailing comma support in generics
## [0.1.8] - 2020-09-26
-* Fix compatibility of generated code with `forbid(future_incompatible)`
+- 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]
+- [Support `?Sized` bounds in where clauses.][22]
-* [Fix lifetime inference error when an associated type is used in fields.][20]
+- [Fix lifetime inference error when an associated type is used in fields.][20]
-* Suppress `clippy::used_underscore_binding` lint in generated code.
+- Suppress `clippy::used_underscore_binding` lint in generated code.
-* Documentation improvements.
+- Documentation improvements.
[20]: https://github.com/taiki-e/pin-project-lite/pull/20
[22]: https://github.com/taiki-e/pin-project-lite/pull/22
## [0.1.6] - 2020-05-31
-* [Support lifetime bounds in where clauses.][18]
+- [Support lifetime bounds in where clauses.][18]
-* Documentation improvements.
+- Documentation improvements.
[18]: https://github.com/taiki-e/pin-project-lite/pull/18
## [0.1.5] - 2020-05-07
-* [Support overwriting the name of core crate.][14]
+- [Support overwriting the name of core crate.][14]
[14]: https://github.com/taiki-e/pin-project-lite/pull/14
## [0.1.4] - 2020-01-20
-* [Support ?Sized bounds in generic parameters.][9]
+- [Support ?Sized bounds in generic parameters.][9]
[9]: https://github.com/taiki-e/pin-project-lite/pull/9
## [0.1.3] - 2020-01-20
-* [Support lifetime bounds in generic parameters.][7]
+- [Support lifetime bounds in generic parameters.][7]
[7]: https://github.com/taiki-e/pin-project-lite/pull/7
## [0.1.2] - 2020-01-05
-* [Support recognizing default generic parameters.][6]
+- [Support recognizing default generic parameters.][6]
[6]: https://github.com/taiki-e/pin-project-lite/pull/6
## [0.1.1] - 2019-11-15
-* [`pin_project!` macro now determines the visibility of the projection type/method is based on the original type.][5]
+- [`pin_project!` macro now determines the visibility of the projection type/method is based on the original type.][5]
[5]: https://github.com/taiki-e/pin-project-lite/pull/5
@@ -82,7 +143,9 @@ This project adheres to [Semantic Versioning](https://semver.org).
Initial release
-[Unreleased]: https://github.com/taiki-e/pin-project-lite/compare/v0.1.11...HEAD
+[Unreleased]: https://github.com/taiki-e/pin-project-lite/compare/v0.2.1...HEAD
+[0.2.1]: https://github.com/taiki-e/pin-project-lite/compare/v0.2.0...v0.2.1
+[0.2.0]: https://github.com/taiki-e/pin-project-lite/compare/v0.1.11...v0.2.0
[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
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
deleted file mode 100644
index 70c2090..0000000
--- a/CODE_OF_CONDUCT.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# 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 2fecadc..7538f02 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,10 +13,10 @@
[package]
edition = "2018"
name = "pin-project-lite"
-version = "0.1.11"
+version = "0.2.1"
authors = ["Taiki Endo <te316e89@gmail.com>"]
+exclude = ["/.github", "/scripts"]
description = "A lightweight version of pin-project written with declarative macros.\n"
-homepage = "https://github.com/taiki-e/pin-project-lite"
documentation = "https://docs.rs/pin-project-lite"
readme = "README.md"
keywords = ["pin", "macros"]
@@ -25,8 +25,6 @@ license = "Apache-2.0 OR MIT"
repository = "https://github.com/taiki-e/pin-project-lite"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
-
-[dependencies]
[dev-dependencies.rustversion]
version = "1"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index e279d86..539de51 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,15 +1,15 @@
[package]
name = "pin-project-lite"
-version = "0.1.11"
+version = "0.2.1"
authors = ["Taiki Endo <te316e89@gmail.com>"]
edition = "2018"
license = "Apache-2.0 OR MIT"
repository = "https://github.com/taiki-e/pin-project-lite"
-homepage = "https://github.com/taiki-e/pin-project-lite"
documentation = "https://docs.rs/pin-project-lite"
keywords = ["pin", "macros"]
categories = ["no-std", "rust-patterns"]
readme = "README.md"
+exclude = ["/.github", "/scripts"]
description = """
A lightweight version of pin-project written with declarative macros.
"""
@@ -25,8 +25,6 @@ members = [
"tests/no-std",
]
-[dependencies]
-
[dev-dependencies]
rustversion = "1"
static_assertions = "1"
diff --git a/METADATA b/METADATA
index 68b46ad..4d7b0bc 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.11.crate"
+ value: "https://static.crates.io/crates/pin-project-lite/pin-project-lite-0.2.1.crate"
}
- version: "0.1.11"
+ version: "0.2.1"
license_type: NOTICE
last_upgrade_date {
- year: 2020
- month: 10
- day: 26
+ year: 2021
+ month: 1
+ day: 5
}
}
diff --git a/README.md b/README.md
index b6c5b3a..2f93ad0 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1,10 @@
# pin-project-lite
-[![crates-badge]][crates-url]
-[![docs-badge]][docs-url]
-[![license-badge]][license]
-[![rustc-badge]][rustc-url]
-
-[crates-badge]: https://img.shields.io/crates/v/pin-project-lite.svg
-[crates-url]: https://crates.io/crates/pin-project-lite
-[docs-badge]: https://docs.rs/pin-project-lite/badge.svg
-[docs-url]: https://docs.rs/pin-project-lite
-[license-badge]: https://img.shields.io/badge/license-Apache--2.0%20OR%20MIT-blue.svg
-[license]: #license
-[rustc-badge]: https://img.shields.io/badge/rustc-1.37+-lightgray.svg
-[rustc-url]: https://blog.rust-lang.org/2019/08/15/Rust-1.37.0.html
+[![crates.io](https://img.shields.io/crates/v/pin-project-lite.svg?style=flat-square&logo=rust)](https://crates.io/crates/pin-project-lite)
+[![docs.rs](https://img.shields.io/badge/docs.rs-pin--project--lite-blue?style=flat-square)](https://docs.rs/pin-project-lite)
+[![license](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue.svg?style=flat-square)](#license)
+[![rustc](https://img.shields.io/badge/rustc-1.37+-blue.svg?style=flat-square)](https://www.rust-lang.org)
+[![build status](https://img.shields.io/github/workflow/status/taiki-e/pin-project-lite/CI/master?style=flat-square)](https://github.com/taiki-e/pin-project-lite/actions?query=workflow%3ACI+branch%3Amaster)
A lightweight version of [pin-project] written with declarative macros.
@@ -22,14 +14,15 @@ Add this to your `Cargo.toml`:
```toml
[dependencies]
-pin-project-lite = "0.1"
+pin-project-lite = "0.2"
```
-The current pin-project-lite requires Rust 1.37 or later.
+*Compiler support: requires rustc 1.37+*
## Examples
-[`pin_project!`] macro creates a projection type covering all the fields of struct.
+[`pin_project!`] macro creates a projection type covering all the fields of
+struct.
```rust
use pin_project_lite::pin_project;
@@ -52,29 +45,60 @@ impl<T, U> Struct<T, U> {
}
```
+To use [`pin_project!`] on enums, you need to name the projection type
+returned from the method.
+
+```rust
+use pin_project_lite::pin_project;
+use std::pin::Pin;
+
+pin_project! {
+ #[project = EnumProj]
+ enum Enum<T, U> {
+ Variant { #[pin] pinned: T, unpinned: U },
+ }
+}
+
+impl<T, U> Enum<T, U> {
+ fn method(self: Pin<&mut Self>) {
+ match self.project() {
+ EnumProj::Variant { pinned, unpinned } => {
+ let _: Pin<&mut T> = pinned;
+ let _: &mut U = unpinned;
+ }
+ }
+ }
+}
+```
+
## [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.
+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].
+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.)
+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.
+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: No support for custom Drop implementation
@@ -84,12 +108,11 @@ pin-project supports this by [`#[pinned_drop]`][pinned-drop].
pin-project supports this by [`UnsafeUnpin`][unsafe-unpin] and [`!Unpin`][not-unpin].
-### Different: No support for pattern matching and destructing
+### Different: No support for tuple structs and tuple variants
-[pin-project supports this.][naming]
+pin-project supports this.
-[`pin_project!`]: https://docs.rs/pin-project-lite/0.1/pin_project_lite/macro.pin_project.html
-[naming]: https://docs.rs/pin-project/1/pin_project/attr.pin_project.html
+[`pin_project!`]: https://docs.rs/pin-project-lite/0.2/pin_project_lite/macro.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
@@ -97,13 +120,9 @@ pin-project supports this by [`UnsafeUnpin`][unsafe-unpin] and [`!Unpin`][not-un
## License
-Licensed under either of
-
-* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
-* MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
-
-at your option.
-
-### Contribution
+Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or
+[MIT license](LICENSE-MIT) at your option.
-Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall
+be dual licensed as above, without any additional terms or conditions.
diff --git a/ci/install-component.sh b/ci/install-component.sh
deleted file mode 100755
index dbba7b1..0000000
--- a/ci/install-component.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/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
-
-package="${1:?}"
-target="${2:-x86_64-unknown-linux-gnu}"
-
-date=$(curl -sSf https://rust-lang.github.io/rustup-components-history/"${target}"/"${package}")
-
-# shellcheck disable=1090
-"$(cd "$(dirname "${0}")" && pwd)"/install-rust.sh nightly-"${date}"
-
-rustup component add "${package}"
-
-case "${package}" in
- rustfmt) "${package}" -V ;;
- *) cargo "${package}" -V ;;
-esac
diff --git a/ci/install-rust.sh b/ci/install-rust.sh
deleted file mode 100755
index 92c5877..0000000
--- a/ci/install-rust.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-set -euo pipefail
-
-toolchain="${1:-nightly}"
-
-rustup toolchain install "${toolchain}" --no-self-update --profile minimal
-rustup default "${toolchain}"
-
-rustup -V
-rustc -V
-cargo -V
diff --git a/scripts/README.md b/scripts/README.md
deleted file mode 100644
index 671a9b1..0000000
--- a/scripts/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-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
deleted file mode 100755
index 7d16e93..0000000
--- a/scripts/check-minimal-versions.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/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
deleted file mode 100755
index ec08568..0000000
--- a/scripts/ci.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/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
deleted file mode 100755
index 844ace6..0000000
--- a/scripts/expandtest.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/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 03a6586..b56c71f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -25,29 +25,60 @@
//! }
//! ```
//!
+//! To use [`pin_project!`] on enums, you need to name the projection type
+//! returned from the method.
+//!
+//! ```rust
+//! use pin_project_lite::pin_project;
+//! use std::pin::Pin;
+//!
+//! pin_project! {
+//! #[project = EnumProj]
+//! enum Enum<T, U> {
+//! Variant { #[pin] pinned: T, unpinned: U },
+//! }
+//! }
+//!
+//! impl<T, U> Enum<T, U> {
+//! fn method(self: Pin<&mut Self>) {
+//! match self.project() {
+//! EnumProj::Variant { pinned, unpinned } => {
+//! let _: Pin<&mut T> = pinned;
+//! let _: &mut U = unpinned;
+//! }
+//! }
+//! }
+//! }
+//! ```
+//!
//! # [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.
+//! 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].
+//! 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.)
+//! 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.
+//! 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: No support for custom Drop implementation
//!
@@ -57,31 +88,26 @@
//!
//! pin-project supports this by [`UnsafeUnpin`][unsafe-unpin] and [`!Unpin`][not-unpin].
//!
-//! ## Different: No support for pattern matching and destructing
+//! ## Different: No support for tuple structs and tuple variants
//!
-//! [pin-project supports this.][naming]
+//! pin-project supports this.
//!
-//! [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))
+ attr(
+ deny(warnings, rust_2018_idioms, single_use_lifetimes),
+ allow(dead_code, unused_variables)
+ )
))]
#![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
-)]
// ANDROID: Use std to allow building as a dylib.
extern crate std;
@@ -105,9 +131,61 @@ extern crate std;
/// # }
/// ```
///
-/// 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)`.
+/// By passing an attribute with the same name as the method to the macro,
+/// you can name the projection type returned from the method. This allows you
+/// to use pattern matching on the projected types.
+///
+/// ```rust
+/// # use pin_project_lite::pin_project;
+/// # use std::pin::Pin;
+/// pin_project! {
+/// #[project = EnumProj]
+/// enum Enum<T> {
+/// Variant { #[pin] field: T },
+/// }
+/// }
+///
+/// impl<T> Enum<T> {
+/// fn method(self: Pin<&mut Self>) {
+/// let this: EnumProj<'_, T> = self.project();
+/// match this {
+/// EnumProj::Variant { field } => {
+/// let _: Pin<&mut T> = field;
+/// }
+/// }
+/// }
+/// }
+/// ```
+///
+/// The `#[project]` (and `#[project_ref]`) attribute must precede the other
+/// attributes except for `#[doc]`. For example, the following code will not be compiled:
+///
+/// ```rust,compile_fail
+/// # use pin_project_lite::pin_project;
+/// # use std::pin::Pin;
+/// pin_project! {
+/// /// documents (`#[doc]`) can be placed before `#[project]`.
+/// #[derive(Clone)] // <--- ERROR
+/// #[project = EnumProj]
+/// #[derive(Debug)] // <--- Ok
+/// enum Enum<T> {
+/// Variant { #[pin] field: T },
+/// }
+/// }
+/// ```
+///
+/// Also, note that the projection types returned by `project` and `project_ref` have
+/// an additional lifetime at the beginning of generics.
+///
+/// ```text
+/// let this: EnumProj<'_, T> = self.project();
+/// ^^
+/// ```
+///
+/// The visibility of the projected types and projection methods is based on the
+/// original type. However, if the visibility of the original type is `pub`, the
+/// visibility of the projected types and the projection methods is downgraded
+/// to `pub(crate)`.
///
/// # Safety
///
@@ -139,6 +217,36 @@ extern crate std;
/// }
/// ```
///
+/// To use `pin_project!` on enums, you need to name the projection type
+/// returned from the method.
+///
+/// ```rust
+/// use pin_project_lite::pin_project;
+/// use std::pin::Pin;
+///
+/// pin_project! {
+/// #[project = EnumProj]
+/// enum Enum<T> {
+/// Struct {
+/// #[pin]
+/// field: T,
+/// },
+/// Unit,
+/// }
+/// }
+///
+/// impl<T> Enum<T> {
+/// fn method(self: Pin<&mut Self>) {
+/// match self.project() {
+/// EnumProj::Struct { field } => {
+/// let _: Pin<&mut T> = field;
+/// }
+/// EnumProj::Unit => {}
+/// }
+/// }
+/// }
+/// ```
+///
/// 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`].
@@ -189,14 +297,53 @@ extern crate std;
/// [pin-project]: https://github.com/taiki-e/pin-project
#[macro_export]
macro_rules! pin_project {
- ($($tt:tt)*) => {
- $crate::__pin_project_internal! { $($tt)* }
+ // Parses options
+ (
+ $(#[doc $($doc:tt)*])*
+ #[project = $proj_mut_ident:ident]
+ #[project_ref = $proj_ref_ident:ident]
+ $($tt:tt)*
+ ) => {
+ $crate::__pin_project_internal! {
+ [$proj_mut_ident][$proj_ref_ident]
+ $(#[doc $($doc)*])*
+ $($tt)*
+ }
+ };
+ (
+ $(#[doc $($doc:tt)*])*
+ #[project = $proj_mut_ident:ident]
+ $($tt:tt)*
+ ) => {
+ $crate::__pin_project_internal! {
+ [$proj_mut_ident][]
+ $(#[doc $($doc)*])*
+ $($tt)*
+ }
+ };
+ (
+ $(#[doc $($doc:tt)*])*
+ #[project_ref = $proj_ref_ident:ident]
+ $($tt:tt)*
+ ) => {
+ $crate::__pin_project_internal! {
+ [][$proj_ref_ident]
+ $(#[doc $($doc)*])*
+ $($tt)*
+ }
+ };
+ (
+ $($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 tuple structs and tuple variant (wontfix).
// * no support for multiple trait/lifetime bounds.
// * no support for `Self` in where clauses. (wontfix)
// * no support for overlapping lifetime names. (wontfix)
@@ -209,8 +356,10 @@ macro_rules! pin_project {
#[macro_export]
macro_rules! __pin_project_internal {
// =============================================================================================
- // main: struct
- (@struct_internal;
+ // struct:main
+ (@struct=>internal;
+ [$($proj_mut_ident:ident)?]
+ [$($proj_ref_ident:ident)?]
[$proj_vis:vis]
[$(#[$attrs:meta])* $vis:vis struct $ident:ident]
[$($def_generics:tt)*]
@@ -232,14 +381,56 @@ macro_rules! __pin_project_internal {
),+
}
+ $crate::__pin_project_internal! { @struct=>make_proj_ty=>named;
+ [$proj_vis]
+ [$($proj_mut_ident)?]
+ [make_proj_field_mut]
+ [$ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ {
+ $(
+ $(#[$pin])?
+ $field_vis $field: $field_ty
+ ),+
+ }
+ }
+ $crate::__pin_project_internal! { @struct=>make_proj_ty=>named;
+ [$proj_vis]
+ [$($proj_ref_ident)?]
+ [make_proj_field_ref]
+ [$ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ {
+ $(
+ $(#[$pin])?
+ $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;
+ $crate::__pin_project_internal! { @struct=>make_proj_ty=>unnamed;
+ [$proj_vis]
+ [$($proj_mut_ident)?][Projection]
+ [make_proj_field_mut]
+ [$ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ {
+ $(
+ $(#[$pin])?
+ $field_vis $field: $field_ty
+ ),+
+ }
+ }
+ $crate::__pin_project_internal! { @struct=>make_proj_ty=>unnamed;
[$proj_vis]
- [$vis struct $ident]
+ [$($proj_ref_ident)?][ProjectionRef]
+ [make_proj_field_ref]
+ [$ident]
[$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
{
$(
@@ -253,32 +444,28 @@ macro_rules! __pin_project_internal {
$(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
- )
- ),+
- }
+ $crate::__pin_project_internal! { @struct=>make_proj_method;
+ [$proj_vis]
+ [$($proj_mut_ident)?][Projection]
+ [project get_unchecked_mut mut]
+ [$($ty_generics)*]
+ {
+ $(
+ $(#[$pin])?
+ $field_vis $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! { @struct=>make_proj_method;
+ [$proj_vis]
+ [$($proj_ref_ident)?][ProjectionRef]
+ [project_ref get_ref]
+ [$($ty_generics)*]
+ {
+ $(
+ $(#[$pin])?
+ $field_vis $field
+ ),+
}
}
}
@@ -322,12 +509,174 @@ macro_rules! __pin_project_internal {
}
};
};
+ // =============================================================================================
+ // enum:main
+ (@enum=>internal;
+ [$($proj_mut_ident:ident)?]
+ [$($proj_ref_ident:ident)?]
+ [$proj_vis:vis]
+ [$(#[$attrs:meta])* $vis:vis enum $ident:ident]
+ [$($def_generics:tt)*]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
+ {
+ $(
+ $(#[$variant_attrs:meta])*
+ $variant:ident $({
+ $(
+ $(#[$pin:ident])?
+ $field:ident: $field_ty:ty
+ ),+
+ })?
+ ),+
+ }
+ ) => {
+ $(#[$attrs])*
+ $vis enum $ident $($def_generics)*
+ $(where
+ $($where_clause)*)?
+ {
+ $(
+ $(#[$variant_attrs])*
+ $variant $({
+ $(
+ $field: $field_ty
+ ),+
+ })?
+ ),+
+ }
+
+ $crate::__pin_project_internal! { @enum=>make_proj_ty;
+ [$proj_vis]
+ [$($proj_mut_ident)?]
+ [make_proj_field_mut]
+ [$ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ {
+ $(
+ $variant $({
+ $(
+ $(#[$pin])?
+ $field: $field_ty
+ ),+
+ })?
+ ),+
+ }
+ }
+ $crate::__pin_project_internal! { @enum=>make_proj_ty;
+ [$proj_vis]
+ [$($proj_ref_ident)?]
+ [make_proj_field_ref]
+ [$ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ {
+ $(
+ $variant $({
+ $(
+ $(#[$pin])?
+ $field: $field_ty
+ ),+
+ })?
+ ),+
+ }
+ }
+
+ #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
+ #[allow(clippy::used_underscore_binding)]
+ const _: () = {
+ impl <$($impl_generics)*> $ident <$($ty_generics)*>
+ $(where
+ $($where_clause)*)?
+ {
+ $crate::__pin_project_internal! { @enum=>make_proj_method;
+ [$proj_vis]
+ [$($proj_mut_ident)?]
+ [project get_unchecked_mut mut]
+ [$($ty_generics)*]
+ {
+ $(
+ $variant $({
+ $(
+ $(#[$pin])?
+ $field
+ ),+
+ })?
+ ),+
+ }
+ }
+ $crate::__pin_project_internal! { @enum=>make_proj_method;
+ [$proj_vis]
+ [$($proj_ref_ident)?]
+ [project_ref get_ref]
+ [$($ty_generics)*]
+ {
+ $(
+ $variant $({
+ $(
+ $(#[$pin])?
+ $field
+ ),+
+ })?
+ ),+
+ }
+ }
+ }
+
+ $crate::__pin_project_internal! { @make_unpin_impl;
+ [$vis $ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ $(
+ $variant: ($(
+ $(
+ $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)*)?]
+ }
+
+ // We don't need to check for '#[repr(packed)]',
+ // since it does not apply to enums.
+ };
+ };
// =============================================================================================
- // make_proj_ty: struct
- (@make_proj_ty_struct;
+ // struct:make_proj_ty
+ (@struct=>make_proj_ty=>unnamed;
[$proj_vis:vis]
- [$vis:vis struct $ident:ident]
+ [$_proj_ty_ident:ident][$proj_ty_ident:ident]
+ [$make_proj_field:ident]
+ [$ident:ident]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+ $($field:tt)*
+ ) => {};
+ (@struct=>make_proj_ty=>unnamed;
+ [$proj_vis:vis]
+ [][$proj_ty_ident:ident]
+ [$make_proj_field:ident]
+ [$ident:ident]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+ $($field:tt)*
+ ) => {
+ $crate::__pin_project_internal! { @struct=>make_proj_ty=>named;
+ [$proj_vis]
+ [$proj_ty_ident]
+ [$make_proj_field]
+ [$ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ $($field)*
+ }
+ };
+ (@struct=>make_proj_ty=>named;
+ [$proj_vis:vis]
+ [$proj_ty_ident:ident]
+ [$make_proj_field:ident]
+ [$ident:ident]
[$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
{
$(
@@ -337,33 +686,171 @@ 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(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
+ #[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`. (only needed for project)
+ #[allow(clippy::redundant_pub_crate)]
#[allow(clippy::type_repetition_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/4326
- $proj_vis struct Projection <'__pin, $($impl_generics)*>
+ $proj_vis struct $proj_ty_ident <'__pin, $($impl_generics)*>
where
$ident <$($ty_generics)*>: '__pin
$(, $($where_clause)*)?
{
$(
- $field_vis $field: $crate::__pin_project_internal!(@make_proj_field;
- $(#[$pin])? $field_ty; mut
+ $field_vis $field: $crate::__pin_project_internal!(@$make_proj_field;
+ $(#[$pin])? $field_ty
)
),+
}
+ };
+ (@struct=>make_proj_ty=>named;
+ [$proj_vis:vis]
+ []
+ [$make_proj_field:ident]
+ [$ident:ident]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+ $($field:tt)*
+ ) => {};
+ // =============================================================================================
+ // enum:make_proj_ty
+ (@enum=>make_proj_ty;
+ [$proj_vis:vis]
+ [$proj_ty_ident:ident]
+ [$make_proj_field:ident]
+ [$ident:ident]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+ {
+ $(
+ $variant:ident $({
+ $(
+ $(#[$pin:ident])?
+ $field:ident: $field_ty:ty
+ ),+
+ })?
+ ),+
+ }
+ ) => {
#[allow(dead_code)] // This lint warns unused fields/variants.
+ #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
+ #[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`. (only needed for project)
+ #[allow(clippy::redundant_pub_crate)]
#[allow(clippy::type_repetition_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/4326
- $proj_vis struct ProjectionRef <'__pin, $($impl_generics)*>
+ $proj_vis enum $proj_ty_ident <'__pin, $($impl_generics)*>
where
$ident <$($ty_generics)*>: '__pin
$(, $($where_clause)*)?
{
$(
- $field_vis $field: $crate::__pin_project_internal!(@make_proj_field;
- $(#[$pin])? $field_ty;
- )
+ $variant $({
+ $(
+ $field: $crate::__pin_project_internal!(@$make_proj_field;
+ $(#[$pin])? $field_ty
+ )
+ ),+
+ })?
),+
}
};
+ (@enum=>make_proj_ty;
+ [$proj_vis:vis]
+ []
+ [$make_proj_field:ident]
+ [$ident:ident]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+ $($variant:tt)*
+ ) => {};
+
+ // =============================================================================================
+ // struct:make_proj_method
+ (@struct=>make_proj_method;
+ [$proj_vis:vis]
+ [$proj_ty_ident:ident][$_proj_ty_ident:ident]
+ [$method_ident:ident $get_method:ident $($mut:ident)?]
+ [$($ty_generics:tt)*]
+ {
+ $(
+ $(#[$pin:ident])?
+ $field_vis:vis $field:ident
+ ),+
+ }
+ ) => {
+ $proj_vis fn $method_ident<'__pin>(
+ self: $crate::__private::Pin<&'__pin $($mut)? Self>,
+ ) -> $proj_ty_ident <'__pin, $($ty_generics)*> {
+ unsafe {
+ let Self { $($field),* } = self.$get_method();
+ $proj_ty_ident {
+ $(
+ $field: $crate::__pin_project_internal!(@make_unsafe_field_proj;
+ $(#[$pin])? $field
+ )
+ ),+
+ }
+ }
+ }
+ };
+ (@struct=>make_proj_method;
+ [$proj_vis:vis]
+ [][$proj_ty_ident:ident]
+ [$method_ident:ident $get_method:ident $($mut:ident)?]
+ [$($ty_generics:tt)*]
+ $($variant:tt)*
+ ) => {
+ $crate::__pin_project_internal! { @struct=>make_proj_method;
+ [$proj_vis]
+ [$proj_ty_ident][$proj_ty_ident]
+ [$method_ident $get_method $($mut)?]
+ [$($ty_generics)*]
+ $($variant)*
+ }
+ };
+ // =============================================================================================
+ // enum:make_proj_method
+ (@enum=>make_proj_method;
+ [$proj_vis:vis]
+ [$proj_ty_ident:ident]
+ [$method_ident:ident $get_method:ident $($mut:ident)?]
+ [$($ty_generics:tt)*]
+ {
+ $(
+ $variant:ident $({
+ $(
+ $(#[$pin:ident])?
+ $field:ident
+ ),+
+ })?
+ ),+
+ }
+ ) => {
+ $proj_vis fn $method_ident<'__pin>(
+ self: $crate::__private::Pin<&'__pin $($mut)? Self>,
+ ) -> $proj_ty_ident <'__pin, $($ty_generics)*> {
+ unsafe {
+ match self.$get_method() {
+ $(
+ Self::$variant $({
+ $($field),+
+ })? => {
+ $proj_ty_ident::$variant $({
+ $(
+ $field: $crate::__pin_project_internal!(
+ @make_unsafe_field_proj;
+ $(#[$pin])? $field
+ )
+ ),+
+ })?
+ }
+ ),+
+ }
+ }
+ }
+ };
+ (@enum=>make_proj_method;
+ [$proj_vis:vis]
+ []
+ [$method_ident:ident $get_method:ident $($mut:ident)?]
+ [$($ty_generics:tt)*]
+ $($variant:tt)*
+ ) => {};
// =============================================================================================
// make_unpin_impl
@@ -397,6 +884,7 @@ macro_rules! __pin_project_internal {
// regardless of the privacy of the types of their fields.
//
// See also https://github.com/taiki-e/pin-project/pull/53.
+ #[allow(non_snake_case)]
$vis struct __Origin <'__pin, $($impl_generics)*>
$(where
$($where_clause)*)?
@@ -467,23 +955,36 @@ macro_rules! __pin_project_internal {
// =============================================================================================
// make_proj_field
- (@make_proj_field;
+ (@make_proj_field_mut;
+ #[pin]
+ $field_ty:ty
+ ) => {
+ $crate::__private::Pin<&'__pin mut ($field_ty)>
+ };
+ (@make_proj_field_mut;
+ $field_ty:ty
+ ) => {
+ &'__pin mut ($field_ty)
+ };
+ (@make_proj_field_ref;
#[pin]
- $field_ty:ty;
- $($mut:ident)?
+ $field_ty:ty
) => {
- $crate::__private::Pin<&'__pin $($mut)? ($field_ty)>
+ $crate::__private::Pin<&'__pin ($field_ty)>
};
- (@make_proj_field;
- $field_ty:ty;
- $($mut:ident)?
+ (@make_proj_field_ref;
+ $field_ty:ty
) => {
- &'__pin $($mut)? ($field_ty)
+ &'__pin ($field_ty)
};
// =============================================================================================
// Parses input and determines visibility
+ // struct
(
+ [$($proj_mut_ident:ident)?]
+ [$($proj_ref_ident:ident)?]
+
$(#[$attrs:meta])*
pub struct $ident:ident $(<
$( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),* $(,)?
@@ -508,7 +1009,9 @@ macro_rules! __pin_project_internal {
),+ $(,)?
}
) => {
- $crate::__pin_project_internal! { @struct_internal;
+ $crate::__pin_project_internal! { @struct=>internal;
+ [$($proj_mut_ident)?]
+ [$($proj_ref_ident)?]
[pub(crate)]
[$(#[$attrs])* pub struct $ident]
[$(<
@@ -543,6 +1046,9 @@ macro_rules! __pin_project_internal {
}
};
(
+ [$($proj_mut_ident:ident)?]
+ [$($proj_ref_ident:ident)?]
+
$(#[$attrs:meta])*
$vis:vis struct $ident:ident $(<
$( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),* $(,)?
@@ -567,7 +1073,9 @@ macro_rules! __pin_project_internal {
),+ $(,)?
}
) => {
- $crate::__pin_project_internal! { @struct_internal;
+ $crate::__pin_project_internal! { @struct=>internal;
+ [$($proj_mut_ident)?]
+ [$($proj_ref_ident)?]
[$vis]
[$(#[$attrs])* $vis struct $ident]
[$(<
@@ -601,6 +1109,155 @@ macro_rules! __pin_project_internal {
}
}
};
+ // enum
+ (
+ [$($proj_mut_ident:ident)?]
+ [$($proj_ref_ident:ident)?]
+
+ $(#[$attrs:meta])*
+ pub enum $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)?
+ ),* $(,)?
+ )?
+ {
+ $(
+ $(#[$variant_attrs:meta])*
+ $variant:ident $({
+ $(
+ $(#[$pin:ident])?
+ $field:ident: $field_ty:ty
+ ),+ $(,)?
+ })?
+ ),+ $(,)?
+ }
+ ) => {
+ $crate::__pin_project_internal! { @enum=>internal;
+ [$($proj_mut_ident)?]
+ [$($proj_ref_ident)?]
+ [pub(crate)]
+ [$(#[$attrs])* pub enum $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)?
+ ),* )?]
+ {
+ $(
+ $(#[$variant_attrs])*
+ $variant $({
+ $(
+ $(#[$pin])?
+ $field: $field_ty
+ ),+
+ })?
+ ),+
+ }
+ }
+ };
+ (
+ [$($proj_mut_ident:ident)?]
+ [$($proj_ref_ident:ident)?]
+
+ $(#[$attrs:meta])*
+ $vis:vis enum $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)?
+ ),* $(,)?
+ )?
+ {
+ $(
+ $(#[$variant_attrs:meta])*
+ $variant:ident $({
+ $(
+ $(#[$pin:ident])?
+ $field:ident: $field_ty:ty
+ ),+ $(,)?
+ })?
+ ),+ $(,)?
+ }
+ ) => {
+ $crate::__pin_project_internal! { @enum=>internal;
+ [$($proj_mut_ident)?]
+ [$($proj_ref_ident)?]
+ [$vis]
+ [$(#[$attrs])* $vis enum $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)?
+ ),* )?]
+ {
+ $(
+ $(#[$variant_attrs])*
+ $variant $({
+ $(
+ $(#[$pin])?
+ $field: $field_ty
+ ),+
+ })?
+ ),+
+ }
+ }
+ };
}
// Not public API.
diff --git a/src/lib.rs.orig b/src/lib.rs.orig
index 0fef95e..8b2283f 100644
--- a/src/lib.rs.orig
+++ b/src/lib.rs.orig
@@ -25,29 +25,60 @@
//! }
//! ```
//!
+//! To use [`pin_project!`] on enums, you need to name the projection type
+//! returned from the method.
+//!
+//! ```rust
+//! use pin_project_lite::pin_project;
+//! use std::pin::Pin;
+//!
+//! pin_project! {
+//! #[project = EnumProj]
+//! enum Enum<T, U> {
+//! Variant { #[pin] pinned: T, unpinned: U },
+//! }
+//! }
+//!
+//! impl<T, U> Enum<T, U> {
+//! fn method(self: Pin<&mut Self>) {
+//! match self.project() {
+//! EnumProj::Variant { pinned, unpinned } => {
+//! let _: Pin<&mut T> = pinned;
+//! let _: &mut U = unpinned;
+//! }
+//! }
+//! }
+//! }
+//! ```
+//!
//! # [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.
+//! 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].
+//! 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.)
+//! 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.
+//! 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: No support for custom Drop implementation
//!
@@ -57,31 +88,26 @@
//!
//! pin-project supports this by [`UnsafeUnpin`][unsafe-unpin] and [`!Unpin`][not-unpin].
//!
-//! ## Different: No support for pattern matching and destructing
+//! ## Different: No support for tuple structs and tuple variants
//!
-//! [pin-project supports this.][naming]
+//! pin-project supports this.
//!
-//! [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))
+ attr(
+ deny(warnings, rust_2018_idioms, single_use_lifetimes),
+ allow(dead_code, unused_variables)
+ )
))]
#![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.
///
@@ -102,9 +128,61 @@
/// # }
/// ```
///
-/// 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)`.
+/// By passing an attribute with the same name as the method to the macro,
+/// you can name the projection type returned from the method. This allows you
+/// to use pattern matching on the projected types.
+///
+/// ```rust
+/// # use pin_project_lite::pin_project;
+/// # use std::pin::Pin;
+/// pin_project! {
+/// #[project = EnumProj]
+/// enum Enum<T> {
+/// Variant { #[pin] field: T },
+/// }
+/// }
+///
+/// impl<T> Enum<T> {
+/// fn method(self: Pin<&mut Self>) {
+/// let this: EnumProj<'_, T> = self.project();
+/// match this {
+/// EnumProj::Variant { field } => {
+/// let _: Pin<&mut T> = field;
+/// }
+/// }
+/// }
+/// }
+/// ```
+///
+/// The `#[project]` (and `#[project_ref]`) attribute must precede the other
+/// attributes except for `#[doc]`. For example, the following code will not be compiled:
+///
+/// ```rust,compile_fail
+/// # use pin_project_lite::pin_project;
+/// # use std::pin::Pin;
+/// pin_project! {
+/// /// documents (`#[doc]`) can be placed before `#[project]`.
+/// #[derive(Clone)] // <--- ERROR
+/// #[project = EnumProj]
+/// #[derive(Debug)] // <--- Ok
+/// enum Enum<T> {
+/// Variant { #[pin] field: T },
+/// }
+/// }
+/// ```
+///
+/// Also, note that the projection types returned by `project` and `project_ref` have
+/// an additional lifetime at the beginning of generics.
+///
+/// ```text
+/// let this: EnumProj<'_, T> = self.project();
+/// ^^
+/// ```
+///
+/// The visibility of the projected types and projection methods is based on the
+/// original type. However, if the visibility of the original type is `pub`, the
+/// visibility of the projected types and the projection methods is downgraded
+/// to `pub(crate)`.
///
/// # Safety
///
@@ -136,6 +214,36 @@
/// }
/// ```
///
+/// To use `pin_project!` on enums, you need to name the projection type
+/// returned from the method.
+///
+/// ```rust
+/// use pin_project_lite::pin_project;
+/// use std::pin::Pin;
+///
+/// pin_project! {
+/// #[project = EnumProj]
+/// enum Enum<T> {
+/// Struct {
+/// #[pin]
+/// field: T,
+/// },
+/// Unit,
+/// }
+/// }
+///
+/// impl<T> Enum<T> {
+/// fn method(self: Pin<&mut Self>) {
+/// match self.project() {
+/// EnumProj::Struct { field } => {
+/// let _: Pin<&mut T> = field;
+/// }
+/// EnumProj::Unit => {}
+/// }
+/// }
+/// }
+/// ```
+///
/// 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`].
@@ -186,14 +294,53 @@
/// [pin-project]: https://github.com/taiki-e/pin-project
#[macro_export]
macro_rules! pin_project {
- ($($tt:tt)*) => {
- $crate::__pin_project_internal! { $($tt)* }
+ // Parses options
+ (
+ $(#[doc $($doc:tt)*])*
+ #[project = $proj_mut_ident:ident]
+ #[project_ref = $proj_ref_ident:ident]
+ $($tt:tt)*
+ ) => {
+ $crate::__pin_project_internal! {
+ [$proj_mut_ident][$proj_ref_ident]
+ $(#[doc $($doc)*])*
+ $($tt)*
+ }
+ };
+ (
+ $(#[doc $($doc:tt)*])*
+ #[project = $proj_mut_ident:ident]
+ $($tt:tt)*
+ ) => {
+ $crate::__pin_project_internal! {
+ [$proj_mut_ident][]
+ $(#[doc $($doc)*])*
+ $($tt)*
+ }
+ };
+ (
+ $(#[doc $($doc:tt)*])*
+ #[project_ref = $proj_ref_ident:ident]
+ $($tt:tt)*
+ ) => {
+ $crate::__pin_project_internal! {
+ [][$proj_ref_ident]
+ $(#[doc $($doc)*])*
+ $($tt)*
+ }
+ };
+ (
+ $($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 tuple structs and tuple variant (wontfix).
// * no support for multiple trait/lifetime bounds.
// * no support for `Self` in where clauses. (wontfix)
// * no support for overlapping lifetime names. (wontfix)
@@ -206,8 +353,10 @@ macro_rules! pin_project {
#[macro_export]
macro_rules! __pin_project_internal {
// =============================================================================================
- // main: struct
- (@struct_internal;
+ // struct:main
+ (@struct=>internal;
+ [$($proj_mut_ident:ident)?]
+ [$($proj_ref_ident:ident)?]
[$proj_vis:vis]
[$(#[$attrs:meta])* $vis:vis struct $ident:ident]
[$($def_generics:tt)*]
@@ -229,14 +378,56 @@ macro_rules! __pin_project_internal {
),+
}
+ $crate::__pin_project_internal! { @struct=>make_proj_ty=>named;
+ [$proj_vis]
+ [$($proj_mut_ident)?]
+ [make_proj_field_mut]
+ [$ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ {
+ $(
+ $(#[$pin])?
+ $field_vis $field: $field_ty
+ ),+
+ }
+ }
+ $crate::__pin_project_internal! { @struct=>make_proj_ty=>named;
+ [$proj_vis]
+ [$($proj_ref_ident)?]
+ [make_proj_field_ref]
+ [$ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ {
+ $(
+ $(#[$pin])?
+ $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;
+ $crate::__pin_project_internal! { @struct=>make_proj_ty=>unnamed;
+ [$proj_vis]
+ [$($proj_mut_ident)?][Projection]
+ [make_proj_field_mut]
+ [$ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ {
+ $(
+ $(#[$pin])?
+ $field_vis $field: $field_ty
+ ),+
+ }
+ }
+ $crate::__pin_project_internal! { @struct=>make_proj_ty=>unnamed;
[$proj_vis]
- [$vis struct $ident]
+ [$($proj_ref_ident)?][ProjectionRef]
+ [make_proj_field_ref]
+ [$ident]
[$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
{
$(
@@ -250,32 +441,28 @@ macro_rules! __pin_project_internal {
$(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
- )
- ),+
- }
+ $crate::__pin_project_internal! { @struct=>make_proj_method;
+ [$proj_vis]
+ [$($proj_mut_ident)?][Projection]
+ [project get_unchecked_mut mut]
+ [$($ty_generics)*]
+ {
+ $(
+ $(#[$pin])?
+ $field_vis $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! { @struct=>make_proj_method;
+ [$proj_vis]
+ [$($proj_ref_ident)?][ProjectionRef]
+ [project_ref get_ref]
+ [$($ty_generics)*]
+ {
+ $(
+ $(#[$pin])?
+ $field_vis $field
+ ),+
}
}
}
@@ -319,12 +506,174 @@ macro_rules! __pin_project_internal {
}
};
};
+ // =============================================================================================
+ // enum:main
+ (@enum=>internal;
+ [$($proj_mut_ident:ident)?]
+ [$($proj_ref_ident:ident)?]
+ [$proj_vis:vis]
+ [$(#[$attrs:meta])* $vis:vis enum $ident:ident]
+ [$($def_generics:tt)*]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)*)?]
+ {
+ $(
+ $(#[$variant_attrs:meta])*
+ $variant:ident $({
+ $(
+ $(#[$pin:ident])?
+ $field:ident: $field_ty:ty
+ ),+
+ })?
+ ),+
+ }
+ ) => {
+ $(#[$attrs])*
+ $vis enum $ident $($def_generics)*
+ $(where
+ $($where_clause)*)?
+ {
+ $(
+ $(#[$variant_attrs])*
+ $variant $({
+ $(
+ $field: $field_ty
+ ),+
+ })?
+ ),+
+ }
+
+ $crate::__pin_project_internal! { @enum=>make_proj_ty;
+ [$proj_vis]
+ [$($proj_mut_ident)?]
+ [make_proj_field_mut]
+ [$ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ {
+ $(
+ $variant $({
+ $(
+ $(#[$pin])?
+ $field: $field_ty
+ ),+
+ })?
+ ),+
+ }
+ }
+ $crate::__pin_project_internal! { @enum=>make_proj_ty;
+ [$proj_vis]
+ [$($proj_ref_ident)?]
+ [make_proj_field_ref]
+ [$ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ {
+ $(
+ $variant $({
+ $(
+ $(#[$pin])?
+ $field: $field_ty
+ ),+
+ })?
+ ),+
+ }
+ }
+
+ #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
+ #[allow(clippy::used_underscore_binding)]
+ const _: () = {
+ impl <$($impl_generics)*> $ident <$($ty_generics)*>
+ $(where
+ $($where_clause)*)?
+ {
+ $crate::__pin_project_internal! { @enum=>make_proj_method;
+ [$proj_vis]
+ [$($proj_mut_ident)?]
+ [project get_unchecked_mut mut]
+ [$($ty_generics)*]
+ {
+ $(
+ $variant $({
+ $(
+ $(#[$pin])?
+ $field
+ ),+
+ })?
+ ),+
+ }
+ }
+ $crate::__pin_project_internal! { @enum=>make_proj_method;
+ [$proj_vis]
+ [$($proj_ref_ident)?]
+ [project_ref get_ref]
+ [$($ty_generics)*]
+ {
+ $(
+ $variant $({
+ $(
+ $(#[$pin])?
+ $field
+ ),+
+ })?
+ ),+
+ }
+ }
+ }
+
+ $crate::__pin_project_internal! { @make_unpin_impl;
+ [$vis $ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ $(
+ $variant: ($(
+ $(
+ $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)*)?]
+ }
+
+ // We don't need to check for '#[repr(packed)]',
+ // since it does not apply to enums.
+ };
+ };
// =============================================================================================
- // make_proj_ty: struct
- (@make_proj_ty_struct;
+ // struct:make_proj_ty
+ (@struct=>make_proj_ty=>unnamed;
[$proj_vis:vis]
- [$vis:vis struct $ident:ident]
+ [$_proj_ty_ident:ident][$proj_ty_ident:ident]
+ [$make_proj_field:ident]
+ [$ident:ident]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+ $($field:tt)*
+ ) => {};
+ (@struct=>make_proj_ty=>unnamed;
+ [$proj_vis:vis]
+ [][$proj_ty_ident:ident]
+ [$make_proj_field:ident]
+ [$ident:ident]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+ $($field:tt)*
+ ) => {
+ $crate::__pin_project_internal! { @struct=>make_proj_ty=>named;
+ [$proj_vis]
+ [$proj_ty_ident]
+ [$make_proj_field]
+ [$ident]
+ [$($impl_generics)*] [$($ty_generics)*] [$(where $($where_clause)*)?]
+ $($field)*
+ }
+ };
+ (@struct=>make_proj_ty=>named;
+ [$proj_vis:vis]
+ [$proj_ty_ident:ident]
+ [$make_proj_field:ident]
+ [$ident:ident]
[$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
{
$(
@@ -334,33 +683,171 @@ 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(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
+ #[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`. (only needed for project)
+ #[allow(clippy::redundant_pub_crate)]
#[allow(clippy::type_repetition_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/4326
- $proj_vis struct Projection <'__pin, $($impl_generics)*>
+ $proj_vis struct $proj_ty_ident <'__pin, $($impl_generics)*>
where
$ident <$($ty_generics)*>: '__pin
$(, $($where_clause)*)?
{
$(
- $field_vis $field: $crate::__pin_project_internal!(@make_proj_field;
- $(#[$pin])? $field_ty; mut
+ $field_vis $field: $crate::__pin_project_internal!(@$make_proj_field;
+ $(#[$pin])? $field_ty
)
),+
}
+ };
+ (@struct=>make_proj_ty=>named;
+ [$proj_vis:vis]
+ []
+ [$make_proj_field:ident]
+ [$ident:ident]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+ $($field:tt)*
+ ) => {};
+ // =============================================================================================
+ // enum:make_proj_ty
+ (@enum=>make_proj_ty;
+ [$proj_vis:vis]
+ [$proj_ty_ident:ident]
+ [$make_proj_field:ident]
+ [$ident:ident]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+ {
+ $(
+ $variant:ident $({
+ $(
+ $(#[$pin:ident])?
+ $field:ident: $field_ty:ty
+ ),+
+ })?
+ ),+
+ }
+ ) => {
#[allow(dead_code)] // This lint warns unused fields/variants.
+ #[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
+ #[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`. (only needed for project)
+ #[allow(clippy::redundant_pub_crate)]
#[allow(clippy::type_repetition_in_bounds)] // https://github.com/rust-lang/rust-clippy/issues/4326
- $proj_vis struct ProjectionRef <'__pin, $($impl_generics)*>
+ $proj_vis enum $proj_ty_ident <'__pin, $($impl_generics)*>
where
$ident <$($ty_generics)*>: '__pin
$(, $($where_clause)*)?
{
$(
- $field_vis $field: $crate::__pin_project_internal!(@make_proj_field;
- $(#[$pin])? $field_ty;
- )
+ $variant $({
+ $(
+ $field: $crate::__pin_project_internal!(@$make_proj_field;
+ $(#[$pin])? $field_ty
+ )
+ ),+
+ })?
),+
}
};
+ (@enum=>make_proj_ty;
+ [$proj_vis:vis]
+ []
+ [$make_proj_field:ident]
+ [$ident:ident]
+ [$($impl_generics:tt)*] [$($ty_generics:tt)*] [$(where $($where_clause:tt)* )?]
+ $($variant:tt)*
+ ) => {};
+
+ // =============================================================================================
+ // struct:make_proj_method
+ (@struct=>make_proj_method;
+ [$proj_vis:vis]
+ [$proj_ty_ident:ident][$_proj_ty_ident:ident]
+ [$method_ident:ident $get_method:ident $($mut:ident)?]
+ [$($ty_generics:tt)*]
+ {
+ $(
+ $(#[$pin:ident])?
+ $field_vis:vis $field:ident
+ ),+
+ }
+ ) => {
+ $proj_vis fn $method_ident<'__pin>(
+ self: $crate::__private::Pin<&'__pin $($mut)? Self>,
+ ) -> $proj_ty_ident <'__pin, $($ty_generics)*> {
+ unsafe {
+ let Self { $($field),* } = self.$get_method();
+ $proj_ty_ident {
+ $(
+ $field: $crate::__pin_project_internal!(@make_unsafe_field_proj;
+ $(#[$pin])? $field
+ )
+ ),+
+ }
+ }
+ }
+ };
+ (@struct=>make_proj_method;
+ [$proj_vis:vis]
+ [][$proj_ty_ident:ident]
+ [$method_ident:ident $get_method:ident $($mut:ident)?]
+ [$($ty_generics:tt)*]
+ $($variant:tt)*
+ ) => {
+ $crate::__pin_project_internal! { @struct=>make_proj_method;
+ [$proj_vis]
+ [$proj_ty_ident][$proj_ty_ident]
+ [$method_ident $get_method $($mut)?]
+ [$($ty_generics)*]
+ $($variant)*
+ }
+ };
+ // =============================================================================================
+ // enum:make_proj_method
+ (@enum=>make_proj_method;
+ [$proj_vis:vis]
+ [$proj_ty_ident:ident]
+ [$method_ident:ident $get_method:ident $($mut:ident)?]
+ [$($ty_generics:tt)*]
+ {
+ $(
+ $variant:ident $({
+ $(
+ $(#[$pin:ident])?
+ $field:ident
+ ),+
+ })?
+ ),+
+ }
+ ) => {
+ $proj_vis fn $method_ident<'__pin>(
+ self: $crate::__private::Pin<&'__pin $($mut)? Self>,
+ ) -> $proj_ty_ident <'__pin, $($ty_generics)*> {
+ unsafe {
+ match self.$get_method() {
+ $(
+ Self::$variant $({
+ $($field),+
+ })? => {
+ $proj_ty_ident::$variant $({
+ $(
+ $field: $crate::__pin_project_internal!(
+ @make_unsafe_field_proj;
+ $(#[$pin])? $field
+ )
+ ),+
+ })?
+ }
+ ),+
+ }
+ }
+ }
+ };
+ (@enum=>make_proj_method;
+ [$proj_vis:vis]
+ []
+ [$method_ident:ident $get_method:ident $($mut:ident)?]
+ [$($ty_generics:tt)*]
+ $($variant:tt)*
+ ) => {};
// =============================================================================================
// make_unpin_impl
@@ -394,6 +881,7 @@ macro_rules! __pin_project_internal {
// regardless of the privacy of the types of their fields.
//
// See also https://github.com/taiki-e/pin-project/pull/53.
+ #[allow(non_snake_case)]
$vis struct __Origin <'__pin, $($impl_generics)*>
$(where
$($where_clause)*)?
@@ -464,23 +952,36 @@ macro_rules! __pin_project_internal {
// =============================================================================================
// make_proj_field
- (@make_proj_field;
+ (@make_proj_field_mut;
+ #[pin]
+ $field_ty:ty
+ ) => {
+ $crate::__private::Pin<&'__pin mut ($field_ty)>
+ };
+ (@make_proj_field_mut;
+ $field_ty:ty
+ ) => {
+ &'__pin mut ($field_ty)
+ };
+ (@make_proj_field_ref;
#[pin]
- $field_ty:ty;
- $($mut:ident)?
+ $field_ty:ty
) => {
- $crate::__private::Pin<&'__pin $($mut)? ($field_ty)>
+ $crate::__private::Pin<&'__pin ($field_ty)>
};
- (@make_proj_field;
- $field_ty:ty;
- $($mut:ident)?
+ (@make_proj_field_ref;
+ $field_ty:ty
) => {
- &'__pin $($mut)? ($field_ty)
+ &'__pin ($field_ty)
};
// =============================================================================================
// Parses input and determines visibility
+ // struct
(
+ [$($proj_mut_ident:ident)?]
+ [$($proj_ref_ident:ident)?]
+
$(#[$attrs:meta])*
pub struct $ident:ident $(<
$( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),* $(,)?
@@ -505,7 +1006,9 @@ macro_rules! __pin_project_internal {
),+ $(,)?
}
) => {
- $crate::__pin_project_internal! { @struct_internal;
+ $crate::__pin_project_internal! { @struct=>internal;
+ [$($proj_mut_ident)?]
+ [$($proj_ref_ident)?]
[pub(crate)]
[$(#[$attrs])* pub struct $ident]
[$(<
@@ -540,6 +1043,9 @@ macro_rules! __pin_project_internal {
}
};
(
+ [$($proj_mut_ident:ident)?]
+ [$($proj_ref_ident:ident)?]
+
$(#[$attrs:meta])*
$vis:vis struct $ident:ident $(<
$( $lifetime:lifetime $(: $lifetime_bound:lifetime)? ),* $(,)?
@@ -564,7 +1070,9 @@ macro_rules! __pin_project_internal {
),+ $(,)?
}
) => {
- $crate::__pin_project_internal! { @struct_internal;
+ $crate::__pin_project_internal! { @struct=>internal;
+ [$($proj_mut_ident)?]
+ [$($proj_ref_ident)?]
[$vis]
[$(#[$attrs])* $vis struct $ident]
[$(<
@@ -598,6 +1106,155 @@ macro_rules! __pin_project_internal {
}
}
};
+ // enum
+ (
+ [$($proj_mut_ident:ident)?]
+ [$($proj_ref_ident:ident)?]
+
+ $(#[$attrs:meta])*
+ pub enum $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)?
+ ),* $(,)?
+ )?
+ {
+ $(
+ $(#[$variant_attrs:meta])*
+ $variant:ident $({
+ $(
+ $(#[$pin:ident])?
+ $field:ident: $field_ty:ty
+ ),+ $(,)?
+ })?
+ ),+ $(,)?
+ }
+ ) => {
+ $crate::__pin_project_internal! { @enum=>internal;
+ [$($proj_mut_ident)?]
+ [$($proj_ref_ident)?]
+ [pub(crate)]
+ [$(#[$attrs])* pub enum $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)?
+ ),* )?]
+ {
+ $(
+ $(#[$variant_attrs])*
+ $variant $({
+ $(
+ $(#[$pin])?
+ $field: $field_ty
+ ),+
+ })?
+ ),+
+ }
+ }
+ };
+ (
+ [$($proj_mut_ident:ident)?]
+ [$($proj_ref_ident:ident)?]
+
+ $(#[$attrs:meta])*
+ $vis:vis enum $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)?
+ ),* $(,)?
+ )?
+ {
+ $(
+ $(#[$variant_attrs:meta])*
+ $variant:ident $({
+ $(
+ $(#[$pin:ident])?
+ $field:ident: $field_ty:ty
+ ),+ $(,)?
+ })?
+ ),+ $(,)?
+ }
+ ) => {
+ $crate::__pin_project_internal! { @enum=>internal;
+ [$($proj_mut_ident)?]
+ [$($proj_ref_ident)?]
+ [$vis]
+ [$(#[$attrs])* $vis enum $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)?
+ ),* )?]
+ {
+ $(
+ $(#[$variant_attrs])*
+ $variant $({
+ $(
+ $(#[$pin])?
+ $field: $field_ty
+ ),+
+ })?
+ ),+
+ }
+ }
+ };
}
// Not public API.
diff --git a/tests/auxiliary/mod.rs b/tests/auxiliary/mod.rs
index 1457099..e39037c 100644
--- a/tests/auxiliary/mod.rs
+++ b/tests/auxiliary/mod.rs
@@ -1,4 +1,6 @@
#![allow(dead_code, unused_macros)]
+#![allow(box_pointers, unreachable_pub)]
+#![allow(clippy::restriction)]
macro_rules! assert_unpin {
($ty:ty) => {
diff --git a/tests/compiletest.rs b/tests/compiletest.rs
index d181491..af75bc5 100644
--- a/tests/compiletest.rs
+++ b/tests/compiletest.rs
@@ -1,8 +1,14 @@
#![warn(rust_2018_idioms, single_use_lifetimes)]
-#[rustversion::attr(not(nightly), ignore)]
+use std::env;
+
+#[rustversion::attr(before(2020-12-03), ignore)] // Note: This date is commit-date and the day before the toolchain date.
#[test]
fn ui() {
+ if env::var_os("CI").is_none() {
+ env::set_var("TRYBUILD", "overwrite");
+ }
+
let t = trybuild::TestCases::new();
t.compile_fail("tests/ui/*.rs");
}
diff --git a/tests/include/basic.rs b/tests/include/basic.rs
index 967cf81..25121f2 100644
--- a/tests/include/basic.rs
+++ b/tests/include/basic.rs
@@ -8,3 +8,28 @@
pub unpinned: U,
}
}
+
+::pin_project_lite::pin_project! {
+ #[project = DefaultStructProj]
+ #[project_ref = DefaultStructProjRef]
+ #[derive(Debug)]
+ pub struct DefaultStructNamed<T, U> {
+ #[pin]
+ pub pinned: T,
+ pub unpinned: U,
+ }
+}
+
+::pin_project_lite::pin_project! {
+ #[project = DefaultEnumProj]
+ #[project_ref = DefaultEnumProjRef]
+ #[derive(Debug)]
+ pub enum DefaultEnum<T, U> {
+ Struct {
+ #[pin]
+ pinned: T,
+ unpinned: U,
+ },
+ Unit,
+ }
+}
diff --git a/tests/lint.rs b/tests/lint.rs
index e81a13c..bbc3033 100644
--- a/tests/lint.rs
+++ b/tests/lint.rs
@@ -40,6 +40,8 @@
// Check interoperability with rustc and clippy lints.
+mod auxiliary;
+
pub mod basic {
include!("include/basic.rs");
}
@@ -55,6 +57,20 @@ pub mod box_pointers {
pub u: Box<isize>,
}
}
+
+ pin_project! {
+ #[project = EnumProj]
+ #[project_ref = EnumProjRef]
+ #[derive(Debug)]
+ pub enum Enum {
+ Struct {
+ #[pin]
+ p: Box<isize>,
+ u: Box<isize>,
+ },
+ Unit,
+ }
+ }
}
pub mod explicit_outlives_requirements {
@@ -72,6 +88,40 @@ pub mod explicit_outlives_requirements {
pub unpinned: &'a mut U,
}
}
+
+ pin_project! {
+ #[project = EnumProj]
+ #[project_ref = EnumProjRef]
+ #[derive(Debug)]
+ pub enum Enum<'a, T, U>
+ where
+ T: ?Sized,
+ U: ?Sized,
+ {
+ Struct {
+ #[pin]
+ pinned: &'a mut T,
+ unpinned: &'a mut U,
+ },
+ Unit,
+ }
+ }
+}
+
+pub mod variant_size_differences {
+ use pin_project_lite::pin_project;
+
+ pin_project! {
+ #[project = EnumProj]
+ #[project_ref = EnumProjRef]
+ #[allow(missing_debug_implementations, missing_copy_implementations)] // https://github.com/rust-lang/rust/pull/74060
+ #[allow(variant_size_differences)] // for the type itself
+ #[allow(clippy::large_enum_variant)] // for the type itself
+ pub enum Enum {
+ V1 { f: u8 },
+ V2 { f: [u8; 1024] },
+ }
+ }
}
pub mod clippy_mut_mut {
@@ -85,6 +135,20 @@ pub mod clippy_mut_mut {
pub unpinned: &'a mut U,
}
}
+
+ pin_project! {
+ #[project = EnumProj]
+ #[project_ref = EnumProjRef]
+ #[derive(Debug)]
+ pub enum Enum<'a, T, U> {
+ Struct {
+ #[pin]
+ pinned: &'a mut T,
+ unpinned: &'a mut U,
+ },
+ Unit,
+ }
+ }
}
#[allow(unreachable_pub)]
@@ -99,6 +163,21 @@ mod clippy_redundant_pub_crate {
pub unpinned: U,
}
}
+
+ #[allow(dead_code)]
+ pin_project! {
+ #[project = EnumProj]
+ #[project_ref = EnumProjRef]
+ #[derive(Debug)]
+ pub enum Enum<T, U> {
+ Struct {
+ #[pin]
+ pinned: T,
+ unpinned: U,
+ },
+ Unit,
+ }
+ }
}
pub mod clippy_type_repetition_in_bounds {
@@ -115,6 +194,23 @@ pub mod clippy_type_repetition_in_bounds {
pub unpinned: U,
}
}
+
+ pin_project! {
+ #[project = EnumProj]
+ #[project_ref = EnumProjRef]
+ #[derive(Debug)]
+ pub enum Enum<T, U>
+ where
+ Enum<T, U>: Sized,
+ {
+ Struct {
+ #[pin]
+ pinned: T,
+ unpinned: U,
+ },
+ Unit,
+ }
+ }
}
pub mod clippy_used_underscore_binding {
@@ -128,43 +224,17 @@ pub mod clippy_used_underscore_binding {
pub _unpinned: U,
}
}
-}
-#[allow(box_pointers)]
-#[allow(clippy::restriction)]
-#[rustversion::attr(not(nightly), ignore)]
-#[test]
-fn check_lint_list() {
- use std::{env, fs, path::PathBuf, process::Command, str};
-
- 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)?;
- }
+ pin_project! {
+ #[project = EnumProj]
+ #[project_ref = EnumProjRef]
+ #[derive(Debug)]
+ pub enum Enum<T, U> {
+ Struct {
+ #[pin]
+ _pinned: T,
+ _unpinned: U,
+ },
}
- 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
deleted file mode 100644
index e4c9f98..0000000
--- a/tests/lint.txt
+++ /dev/null
@@ -1,148 +0,0 @@
-
-Available lint options:
- -W <foo> Warn about <foo>
- -A <foo> Allow <foo>
- -D <foo> Deny <foo>
- -F <foo> Forbid <foo> (deny <foo> and all attempts to override)
-
-
-Lint checks provided by rustc:
-
- name default meaning
- ---- ------- -------
- absolute-paths-not-starting-with-crate allow fully qualified paths that start with a module name instead of `crate`, `self`, or an extern crate name
- anonymous-parameters allow detects anonymous parameters
- box-pointers allow use of owned (Box type) heap memory
- deprecated-in-future allow detects use of items that will be deprecated in a future version
- elided-lifetimes-in-paths allow hidden lifetime parameters in types are deprecated
- explicit-outlives-requirements allow outlives requirements can be inferred
- invalid-html-tags allow detects invalid HTML tags in doc comments
- keyword-idents allow detects edition keywords being used as an identifier
- macro-use-extern-crate allow the `#[macro_use]` attribute is now deprecated in favor of using macros via the module system
- meta-variable-misuse allow possible meta-variable misuse at macro definition
- missing-copy-implementations allow detects potentially-forgotten implementations of `Copy`
- missing-crate-level-docs allow detects crates with no crate-level documentation
- missing-debug-implementations allow detects missing implementations of Debug
- missing-docs allow detects missing documentation for public members
- missing-doc-code-examples allow detects publicly-exported items without code samples in their documentation
- non-ascii-idents allow detects non-ASCII identifiers
- pointer-structural-match allow pointers are not structural-match
- private-doc-tests allow detects code samples in docs of private items not documented by rustdoc
- single-use-lifetimes allow detects lifetime parameters that are only used once
- trivial-casts allow detects trivial casts which could be removed
- trivial-numeric-casts allow detects trivial casts of numeric types which could be removed
- unaligned-references allow detects unaligned references to fields of packed structs
- unreachable-pub allow `pub` items not reachable from crate root
- unsafe-code allow usage of `unsafe` code
- unsafe-op-in-unsafe-fn allow unsafe operations in unsafe functions without an explicit unsafe block are deprecated
- unstable-features allow enabling unstable features (deprecated. do not use)
- unused-crate-dependencies allow crate dependencies that are never used
- unused-extern-crates allow extern crates that are never used
- unused-import-braces allow unnecessary braces around an imported item
- unused-lifetimes allow detects lifetime parameters that are never used
- unused-qualifications allow detects unnecessarily qualified names
- unused-results allow unused result of an expression in a statement
- variant-size-differences allow detects enums with widely varying variant sizes
- array-into-iter warn detects calling `into_iter` on arrays
- asm-sub-register warn using only a subset of a register for inline asm inputs
- bare-trait-objects warn suggest using `dyn Trait` for trait objects
- bindings-with-variant-name warn detects pattern bindings with the same name as one of the matched variants
- broken-intra-doc-links warn failures in resolving intra-doc link targets
- cenum-impl-drop-cast warn a C-like enum implementing Drop is cast
- clashing-extern-declarations warn detects when an extern fn has been declared with the same name but different types
- coherence-leak-check warn distinct impls distinguished only by the leak-check code
- confusable-idents warn detects visually confusable pairs between identifiers
- const-evaluatable-unchecked warn detects a generic constant is used in a type without a emitting a warning
- const-item-mutation warn detects attempts to mutate a `const` item
- dead-code warn detect unused, unexported items
- deprecated warn detects use of deprecated items
- drop-bounds warn bounds of the form `T: Drop` are useless
- ellipsis-inclusive-range-patterns warn `...` range patterns are deprecated
- exported-private-dependencies warn public interface leaks type from a private dependency
- illegal-floating-point-literal-pattern warn floating-point literals cannot be used in patterns
- improper-ctypes warn proper use of libc types in foreign modules
- improper-ctypes-definitions warn proper use of libc types in foreign item definitions
- incomplete-features warn incomplete features that may function improperly in some or all cases
- indirect-structural-match warn constant used in pattern contains value of non-structural-match type in a field or a variant
- inline-no-sanitize warn detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]`
- invalid-codeblock-attributes warn codeblock attribute looks a lot like a known one
- invalid-value warn an invalid value is being created (such as a NULL reference)
- irrefutable-let-patterns warn detects irrefutable patterns in if-let and while-let statements
- late-bound-lifetime-arguments warn detects generic lifetime arguments in path segments with late bound lifetime parameters
- mixed-script-confusables warn detects Unicode scripts whose mixed script confusables codepoints are solely used
- mutable-borrow-reservation-conflict warn reservation of a two-phased borrow conflicts with other shared borrows
- nontrivial-structural-match warn constant used in pattern of non-structural-match type and the constant's initializer expression contains values of non-structural-match types
- non-camel-case-types warn types, variants, traits and type parameters should have camel case names
- non-shorthand-field-patterns warn using `Struct { x: x }` instead of `Struct { x }` in a pattern
- non-snake-case warn variables, methods, functions, lifetime parameters and modules should have snake case names
- non-upper-case-globals warn static constants should have uppercase identifiers
- no-mangle-generic-items warn generic items must be mangled
- overlapping-patterns warn detects overlapping patterns
- path-statements warn path statements with no effect
- private-in-public warn detect private items in public interfaces not caught by the old implementation
- proc-macro-derive-resolution-fallback warn detects proc macro derives using inaccessible names from parent modules
- redundant-semicolons warn detects unnecessary trailing semicolons
- renamed-and-removed-lints warn lints that have been renamed or removed
- safe-packed-borrows warn safe borrows of fields of packed structs were erroneously allowed
- stable-features warn stable features found in `#[feature]` directive
- trivial-bounds warn these bounds don't depend on an type parameters
- type-alias-bounds warn bounds in type aliases are not enforced
- tyvar-behind-raw-pointer warn raw pointer to an inference variable
- uncommon-codepoints warn detects uncommon Unicode codepoints in identifiers
- unconditional-recursion warn functions that cannot return without calling themselves
- unknown-lints warn unrecognized lint attribute
- unnameable-test-items warn detects an item that cannot be named being marked as `#[test_case]`
- unreachable-code warn detects unreachable code paths
- unreachable-patterns warn detects unreachable patterns
- unstable-name-collisions warn detects name collision with an existing but unstable method
- unused-allocation warn detects unnecessary allocations that can be eliminated
- unused-assignments warn detect assignments that will never be read
- unused-attributes warn detects attributes that were not used by the compiler
- unused-braces warn unnecessary braces around an expression
- unused-comparisons warn comparisons made useless by limits of the types involved
- unused-doc-comments warn detects doc comments that aren't used by rustdoc
- unused-features warn unused features found in crate-level `#[feature]` directives
- unused-imports warn imports that are never used
- unused-labels warn detects labels that are never used
- unused-macros warn detects macros that were not used
- unused-must-use warn unused result of a type flagged as `#[must_use]`
- unused-mut warn detect mut variables which don't need to be mutable
- unused-parens warn `if`, `match`, `while` and `return` do not need parentheses
- unused-unsafe warn unnecessary use of an `unsafe` block
- unused-variables warn detect variables which are not used in any way
- warnings warn mass-change the level for lints which produce warnings
- where-clauses-object-safety warn checks the object safety of where clauses
- while-true warn suggest using `loop { }` instead of `while true { }`
- ambiguous-associated-items deny ambiguous associated items
- arithmetic-overflow deny arithmetic operation overflows
- conflicting-repr-hints deny conflicts between `#[repr(..)]` hints that were previously accepted and used in practice
- const-err deny constant evaluation detected erroneous expression
- ill-formed-attribute-input deny ill-formed attribute inputs that were previously accepted and used in practice
- 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
- mutable-transmutes deny mutating transmuted &mut T from &T may cause undefined behavior
- no-mangle-const-items deny const items will not have their symbols exported
- order-dependent-trait-objects deny trait-object types were treated as different depending on marker-trait order
- overflowing-literals deny literal out of range for its type
- patterns-in-fns-without-body deny patterns in functions without body were erroneously allowed
- pub-use-of-private-extern-crate deny detect public re-exports of private extern crates
- soft-unstable deny a feature gate that doesn't break dependent crates
- unconditional-panic deny operation will cause a panic at runtime
- unknown-crate-types deny unknown crate type found in `#[crate_type]` directive
-
-
-Lint groups provided by rustc:
-
- name sub-lints
- ---- ---------
- warnings all lints that are set to issue warnings
- future-incompatible keyword-idents, anonymous-parameters, illegal-floating-point-literal-pattern, private-in-public, pub-use-of-private-extern-crate, invalid-type-param-default, safe-packed-borrows, patterns-in-fns-without-body, 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 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
-
-
-Compiler plugins can provide additional lints and lint groups. To see a listing of these, re-run `rustc -W help` with a crate filename.
diff --git a/tests/proper_unpin.rs b/tests/proper_unpin.rs
index bbee78c..b1c72c1 100644
--- a/tests/proper_unpin.rs
+++ b/tests/proper_unpin.rs
@@ -16,17 +16,34 @@ pub mod default {
assert_not_unpin!(Inner<PhantomPinned>);
pin_project! {
- struct Foo<T, U> {
+ struct Struct<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>);
+ assert_unpin!(Struct<(), ()>);
+ assert_unpin!(Struct<(), PhantomPinned>);
+ assert_not_unpin!(Struct<PhantomPinned, ()>);
+ assert_not_unpin!(Struct<PhantomPinned, PhantomPinned>);
+
+ pin_project! {
+ #[project = EnumProj]
+ #[project_ref = EnumProjRef]
+ enum Enum<T, U> {
+ V1 {
+ #[pin]
+ f1: Inner<T>,
+ f2: U,
+ },
+ }
+ }
+
+ assert_unpin!(Enum<(), ()>);
+ assert_unpin!(Enum<(), PhantomPinned>);
+ assert_not_unpin!(Enum<PhantomPinned, ()>);
+ assert_not_unpin!(Enum<PhantomPinned, PhantomPinned>);
pin_project! {
struct TrivialBounds {
@@ -38,12 +55,12 @@ pub mod default {
assert_not_unpin!(TrivialBounds);
pin_project! {
- struct Bar<'a, T, U> {
+ struct PinRef<'a, T, U> {
#[pin]
f1: &'a mut Inner<T>,
f2: U,
}
}
- assert_unpin!(Bar<'_, PhantomPinned, PhantomPinned>);
+ assert_unpin!(PinRef<'_, PhantomPinned, PhantomPinned>);
}
diff --git a/tests/test.rs b/tests/test.rs
index 1af2b59..cd4f48b 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -10,6 +10,8 @@ use pin_project_lite::pin_project;
#[test]
fn projection() {
pin_project! {
+ #[project = StructProj]
+ #[project_ref = StructProjRef]
struct Struct<T, U> {
#[pin]
f1: T,
@@ -21,21 +23,89 @@ fn projection() {
let mut s_orig = Pin::new(&mut s);
let s = s_orig.as_mut().project();
- let x: Pin<&mut i32> = s.f1;
- assert_eq!(*x, 1);
-
- let y: &mut i32 = s.f2;
- assert_eq!(*y, 2);
+ let _: Pin<&mut i32> = s.f1;
+ assert_eq!(*s.f1, 1);
+ let _: &mut i32 = s.f2;
+ assert_eq!(*s.f2, 2);
assert_eq!(s_orig.as_ref().f1, 1);
assert_eq!(s_orig.as_ref().f2, 2);
let mut s = Struct { f1: 1, f2: 2 };
+ let mut s = Pin::new(&mut s);
+ {
+ let StructProj { f1, f2 } = s.as_mut().project();
+ let _: Pin<&mut i32> = f1;
+ let _: &mut i32 = f2;
+ }
+ {
+ let StructProjRef { f1, f2 } = s.as_ref().project_ref();
+ let _: Pin<&i32> = f1;
+ let _: &i32 = f2;
+ }
- let s = Pin::new(&mut s).project();
+ pin_project! {
+ #[project = EnumProj]
+ #[project_ref = EnumProjRef]
+ #[derive(Eq, PartialEq, Debug)]
+ enum Enum<C, D> {
+ Struct {
+ #[pin]
+ f1: C,
+ f2: D,
+ },
+ Unit,
+ }
+ }
- let _: Pin<&mut i32> = s.f1;
- let _: &mut i32 = s.f2;
+ let mut e = Enum::Struct { f1: 1, f2: 2 };
+ let mut e = Pin::new(&mut e);
+
+ match e.as_mut().project() {
+ EnumProj::Struct { f1, f2 } => {
+ let _: Pin<&mut i32> = f1;
+ assert_eq!(*f1, 1);
+ let _: &mut i32 = f2;
+ assert_eq!(*f2, 2);
+ }
+ EnumProj::Unit => unreachable!(),
+ }
+
+ assert_eq!(&*e, &Enum::Struct { f1: 1, f2: 2 });
+
+ if let EnumProj::Struct { f1, f2 } = e.as_mut().project() {
+ let _: Pin<&mut i32> = f1;
+ assert_eq!(*f1, 1);
+ let _: &mut i32 = f2;
+ assert_eq!(*f2, 2);
+ }
+}
+
+#[test]
+fn enum_project_set() {
+ pin_project! {
+ #[project = EnumProj]
+ #[project_ref = EnumProjRef]
+ #[derive(Eq, PartialEq, Debug)]
+ enum Enum {
+ V1 { #[pin] f: u8 },
+ V2 { f: bool },
+ }
+ }
+
+ let mut e = Enum::V1 { f: 25 };
+ let mut e_orig = Pin::new(&mut e);
+ let e_proj = e_orig.as_mut().project();
+
+ match e_proj {
+ EnumProj::V1 { f } => {
+ let new_e = Enum::V2 { f: f.as_ref().get_ref() == &25 };
+ e_orig.set(new_e);
+ }
+ EnumProj::V2 { .. } => unreachable!(),
+ }
+
+ assert_eq!(e, Enum::V2 { f: true });
}
#[test]
@@ -48,6 +118,17 @@ fn where_clause() {
f: T,
}
}
+
+ pin_project! {
+ #[project = EnumProj]
+ #[project_ref = EnumProjRef]
+ enum Enum<T>
+ where
+ T: Copy,
+ {
+ V { f: T },
+ }
+ }
}
#[test]
@@ -86,6 +167,18 @@ fn where_clause_and_associated_type_field() {
trait Static: 'static {}
impl<T> Static for Struct3<T> {}
+
+ pin_project! {
+ #[project = EnumProj]
+ #[project_ref = EnumProjRef]
+ enum Enum<I>
+ where
+ I: Iterator,
+ {
+ V1 { #[pin] f: I },
+ V2 { f: I::Item },
+ }
+ }
}
#[test]
@@ -114,6 +207,20 @@ fn move_out() {
let x = Struct { f: NotCopy };
let _val: NotCopy = x.f;
+
+ pin_project! {
+ #[project = EnumProj]
+ #[project_ref = EnumProjRef]
+ enum Enum {
+ V { f: NotCopy },
+ }
+ }
+
+ let x = Enum::V { f: NotCopy };
+ #[allow(clippy::infallible_destructuring_match)]
+ let _val: NotCopy = match x {
+ Enum::V { f } => f,
+ };
}
#[test]
@@ -154,7 +261,7 @@ fn trait_bounds_on_type_generics() {
}
}
- let _: Struct6<'_> = Struct6 { f: &mut [0u8; 16] };
+ let _: Struct6<'_> = Struct6 { f: &mut [0_u8; 16] };
pin_project! {
pub struct Struct7<T: 'static> {
@@ -172,6 +279,14 @@ fn trait_bounds_on_type_generics() {
f2: &'b u8,
}
}
+
+ pin_project! {
+ #[project = EnumProj]
+ #[project_ref = EnumProjRef]
+ enum Enum<'a, T: ?Sized> {
+ V { f: &'a mut T },
+ }
+ }
}
#[test]
@@ -200,11 +315,23 @@ fn lifetime_project() {
pin_project! {
struct Struct2<'a, T, U> {
#[pin]
- pinned: &'a mut T,
+ pinned: &'a T,
unpinned: U,
}
}
+ pin_project! {
+ #[project = EnumProj]
+ #[project_ref = EnumProjRef]
+ enum Enum<T, U> {
+ V {
+ #[pin]
+ pinned: T,
+ unpinned: U,
+ },
+ }
+ }
+
impl<T, U> Struct1<T, U> {
fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a T> {
self.project_ref().pinned
@@ -221,19 +348,42 @@ fn lifetime_project() {
}
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<'a>(self: Pin<&'a Self>) -> Pin<&'a &'b T> {
self.project_ref().pinned
}
- fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut &'b mut T> {
+ fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut &'b T> {
self.project().pinned
}
- fn get_pin_ref_elided(self: Pin<&Self>) -> Pin<&&'b mut T> {
+ fn get_pin_ref_elided(self: Pin<&Self>) -> Pin<&&'b T> {
self.project_ref().pinned
}
- fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut &'b mut T> {
+ fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut &'b T> {
self.project().pinned
}
}
+
+ impl<T, U> Enum<T, U> {
+ fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a T> {
+ match self.project_ref() {
+ EnumProjRef::V { pinned, .. } => pinned,
+ }
+ }
+ fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut T> {
+ match self.project() {
+ EnumProj::V { pinned, .. } => pinned,
+ }
+ }
+ fn get_pin_ref_elided(self: Pin<&Self>) -> Pin<&T> {
+ match self.project_ref() {
+ EnumProjRef::V { pinned, .. } => pinned,
+ }
+ }
+ fn get_pin_mut_elided(self: Pin<&mut Self>) -> Pin<&mut T> {
+ match self.project() {
+ EnumProj::V { pinned, .. } => pinned,
+ }
+ }
+ }
}
mod visibility {
@@ -278,7 +428,7 @@ fn dst() {
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().f;
+ let _: &mut (dyn core::fmt::Debug) = x.project().f;
pin_project! {
pub struct Struct2<T: ?Sized> {
@@ -289,7 +439,7 @@ fn dst() {
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().f;
+ let _: Pin<&mut (dyn core::fmt::Debug + Unpin)> = x.project().f;
pin_project! {
struct Struct3<T>
@@ -413,3 +563,36 @@ fn trailing_comma() {
// }
// }
}
+
+#[test]
+fn attrs() {
+ pin_project! {
+ #[project = Enum1Proj]
+ #[project_ref = Enum1ProjRef]
+ enum Enum1 {
+ #[cfg(not(any()))]
+ V {
+ f: ()
+ },
+ }
+ }
+
+ pin_project! {
+ /// dox1
+ #[project = Enum2Proj]
+ #[project_ref = Enum2ProjRef]
+ /// dox2
+ #[derive(Debug)]
+ /// dox3
+ enum Enum2 {
+ /// dox4
+ V1 {
+ // TODO
+ // /// dox5
+ f: ()
+ },
+ /// dox6
+ V2,
+ }
+ }
+}
diff --git a/tests/ui/invalid-bounds.stderr b/tests/ui/invalid-bounds.stderr
index 59e9b13..a565cce 100644
--- a/tests/ui/invalid-bounds.stderr
+++ b/tests/ui/invalid-bounds.stderr
@@ -1,14 +1,26 @@
-error: no rules expected the token `:`
- --> $DIR/invalid-bounds.rs:4:33
+error: no rules expected the token `[`
+ --> $DIR/invalid-bounds.rs:3:1
|
-4 | struct Generics1<T: 'static : Sized> { //~ ERROR no rules expected the token `:`
- | ^ no rules expected this token in macro call
+3 | / pin_project! {
+4 | | struct Generics1<T: 'static : Sized> { //~ ERROR no rules expected the token `:`
+5 | | field: T,
+6 | | }
+7 | | }
+ | |_^ no rules expected this token in macro call
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-error: no rules expected the token `:`
- --> $DIR/invalid-bounds.rs:10:33
+error: no rules expected the token `[`
+ --> $DIR/invalid-bounds.rs:9:1
+ |
+9 | / pin_project! {
+10 | | struct Generics2<T: 'static : ?Sized> { //~ ERROR no rules expected the token `:`
+11 | | field: T,
+12 | | }
+13 | | }
+ | |_^ no rules expected this token in macro call
|
-10 | struct Generics2<T: 'static : ?Sized> { //~ ERROR no rules expected the token `:`
- | ^ no rules expected this token in macro call
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected one of `+`, `,`, `=`, or `>`, found `:`
--> $DIR/invalid-bounds.rs:15:1
@@ -58,23 +70,45 @@ error: expected one of `+`, `,`, `=`, or `>`, found `:`
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-error: no rules expected the token `Sized`
- --> $DIR/invalid-bounds.rs:34:34
+error: no rules expected the token `[`
+ --> $DIR/invalid-bounds.rs:33:1
+ |
+33 | / pin_project! {
+34 | | struct Generics6<T: ?Sized : Sized> { //~ ERROR no rules expected the token `Sized`
+35 | | field: T,
+36 | | }
+37 | | }
+ | |_^ no rules expected this token in macro call
|
-34 | struct Generics6<T: ?Sized : Sized> { //~ ERROR no rules expected the token `Sized`
- | ^^^^^ no rules expected this token in macro call
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-error: no rules expected the token `:`
- --> $DIR/invalid-bounds.rs:42:20
+error: no rules expected the token `[`
+ --> $DIR/invalid-bounds.rs:39:1
+ |
+39 | / pin_project! {
+40 | | struct WhereClause1<T>
+41 | | where
+42 | | T: 'static : Sized //~ ERROR no rules expected the token `:`
+... |
+45 | | }
+46 | | }
+ | |_^ no rules expected this token in macro call
|
-42 | T: 'static : Sized //~ ERROR no rules expected the token `:`
- | ^ no rules expected this token in macro call
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-error: no rules expected the token `:`
- --> $DIR/invalid-bounds.rs:51:20
+error: no rules expected the token `[`
+ --> $DIR/invalid-bounds.rs:48:1
+ |
+48 | / pin_project! {
+49 | | struct WhereClause2<T>
+50 | | where
+51 | | T: 'static : ?Sized //~ ERROR no rules expected the token `:`
+... |
+54 | | }
+55 | | }
+ | |_^ no rules expected this token in macro call
|
-51 | T: 'static : ?Sized //~ ERROR no rules expected the token `:`
- | ^ no rules expected this token in macro call
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected `where`, or `{` after struct name, found `:`
--> $DIR/invalid-bounds.rs:57:1
@@ -127,8 +161,16 @@ error: expected `where`, or `{` after struct name, found `:`
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-error: no rules expected the token `Sized`
- --> $DIR/invalid-bounds.rs:87:21
+error: no rules expected the token `[`
+ --> $DIR/invalid-bounds.rs:84:1
|
-87 | T: ?Sized : Sized //~ ERROR no rules expected the token `Sized`
- | ^^^^^ no rules expected this token in macro call
+84 | / pin_project! {
+85 | | struct WhereClause6<T>
+86 | | where
+87 | | T: ?Sized : Sized //~ ERROR no rules expected the token `Sized`
+... |
+90 | | }
+91 | | }
+ | |_^ no rules expected this token in macro call
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/invalid.stderr b/tests/ui/invalid.stderr
index f780e2e..06f2d79 100644
--- a/tests/ui/invalid.stderr
+++ b/tests/ui/invalid.stderr
@@ -1,14 +1,29 @@
-error: no rules expected the token `(`
- --> $DIR/invalid.rs:5:14
+error: no rules expected the token `[`
+ --> $DIR/invalid.rs:3:1
|
-5 | #[pin()] //~ ERROR no rules expected the token `(`
- | ^ no rules expected this token in macro call
+3 | / pin_project! {
+4 | | struct A<T> {
+5 | | #[pin()] //~ ERROR no rules expected the token `(`
+6 | | pinned: T,
+7 | | }
+8 | | }
+ | |_^ no rules expected this token in macro call
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-error: no rules expected the token `#`
- --> $DIR/invalid.rs:20:9
+error: no rules expected the token `[`
+ --> $DIR/invalid.rs:17:1
+ |
+17 | / pin_project! {
+18 | | struct C<T> {
+19 | | #[pin]
+20 | | #[pin] //~ ERROR no rules expected the token `#`
+21 | | pinned: T,
+22 | | }
+23 | | }
+ | |_^ no rules expected this token in macro call
|
-20 | #[pin] //~ ERROR no rules expected the token `#`
- | ^ no rules expected this token in macro call
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot find attribute `pin` in this scope
--> $DIR/invalid.rs:11:7
diff --git a/tests/ui/overlapping_lifetime_names.stderr b/tests/ui/overlapping_lifetime_names.stderr
index f86942c..8a9bb4f 100644
--- a/tests/ui/overlapping_lifetime_names.stderr
+++ b/tests/ui/overlapping_lifetime_names.stderr
@@ -8,7 +8,7 @@ error[E0496]: lifetime name `'__pin` shadows a lifetime name that is already in
6 | | field: &'__pin mut T,
7 | | }
8 | | }
- | |_^ lifetime '__pin already in scope
+ | |_^ lifetime `'__pin` already in scope
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -22,7 +22,7 @@ error[E0496]: lifetime name `'__pin` shadows a lifetime name that is already in
6 | | field: &'__pin mut T,
7 | | }
8 | | }
- | |_^ lifetime '__pin already in scope
+ | |_^ lifetime `'__pin` already in scope
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/unsupported.stderr b/tests/ui/unsupported.stderr
index 4f7b1ae..2cd17df 100644
--- a/tests/ui/unsupported.stderr
+++ b/tests/ui/unsupported.stderr
@@ -1,29 +1,53 @@
-error: no rules expected the token `}`
- --> $DIR/unsupported.rs:4:21
+error: no rules expected the token `[`
+ --> $DIR/unsupported.rs:3:1
|
-4 | struct Struct1 {} //~ ERROR no rules expected the token `}`
- | ^ no rules expected this token in macro call
+3 | / pin_project! {
+4 | | struct Struct1 {} //~ ERROR no rules expected the token `}`
+5 | | }
+ | |_^ no rules expected this token in macro call
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-error: no rules expected the token `(`
- --> $DIR/unsupported.rs:8:19
+error: no rules expected the token `[`
+ --> $DIR/unsupported.rs:7:1
+ |
+7 | / pin_project! {
+8 | | struct Struct2(); //~ ERROR no rules expected the token `(`
+9 | | }
+ | |_^ no rules expected this token in macro call
|
-8 | struct Struct2(); //~ ERROR no rules expected the token `(`
- | ^ no rules expected this token in macro call
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-error: no rules expected the token `;`
- --> $DIR/unsupported.rs:12:19
+error: no rules expected the token `[`
+ --> $DIR/unsupported.rs:11:1
+ |
+11 | / pin_project! {
+12 | | struct Struct3; //~ ERROR no rules expected the token `;`
+13 | | }
+ | |_^ no rules expected this token in macro call
|
-12 | struct Struct3; //~ ERROR no rules expected the token `;`
- | ^ no rules expected this token in macro call
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-error: no rules expected the token `enum`
- --> $DIR/unsupported.rs:16:5
+error: no rules expected the token `[`
+ --> $DIR/unsupported.rs:15:1
|
-16 | enum Enum { //~ ERROR no rules expected the token `enum`
- | ^^^^ no rules expected this token in macro call
+15 | / pin_project! {
+16 | | enum Enum { //~ ERROR no rules expected the token `enum`
+17 | | A(u8)
+18 | | }
+19 | | }
+ | |_^ no rules expected this token in macro call
+ |
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-error: no rules expected the token `union`
- --> $DIR/unsupported.rs:22:5
+error: no rules expected the token `[`
+ --> $DIR/unsupported.rs:21:1
+ |
+21 | / pin_project! {
+22 | | union Union { //~ ERROR no rules expected the token `union`
+23 | | x: u8,
+24 | | }
+25 | | }
+ | |_^ no rules expected this token in macro call
|
-22 | union Union { //~ ERROR no rules expected the token `union`
- | ^^^^^ no rules expected this token in macro call
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)