Initial commit

This commit is contained in:
Taiki Endo
2019-10-23 00:28:55 +09:00
commit ea13ef637e
35 changed files with 1745 additions and 0 deletions
+22
View File
@@ -0,0 +1,22 @@
# EditorConfig configuration
# https://editorconfig.org
# Top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file, utf-8 charset
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
# Match rust/toml, set 4 space indentation
[*.{rs,toml}]
indent_style = space
indent_size = 4
# Match json/yaml/markdown, set 2 space indentation
[*.{json,yml,md}]
indent_style = space
indent_size = 2
+4
View File
@@ -0,0 +1,4 @@
[attr]rust text eol=lf whitespace=tab-in-indent,trailing-space,tabwidth=4
* text=auto eol=lf
*.rs rust
+1
View File
@@ -0,0 +1 @@
* @taiki-e
+10
View File
@@ -0,0 +1,10 @@
status = [
"test (1.37.0)",
"test (stable)",
"test (beta)",
"test (nightly)",
"style (clippy)",
"style (rustfmt)",
"style (rustdoc)",
]
delete_merged_branches = true
+92
View File
@@ -0,0 +1,92 @@
name: ci
on:
pull_request:
push:
branches:
- master
- staging
- trying
schedule:
- cron: 00 01 * * 00 # Weekly
jobs:
test:
name: test
runs-on: ubuntu-latest
env:
RUSTFLAGS: -Dwarnings
strategy:
matrix:
build:
# 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
steps:
- uses: actions/checkout@master
- name: Install Rust
run: |
rustup self update # TODO: when default rustup is bumped to 1.20+, remove this.
rustup set profile minimal
rustup update ${{ matrix.rust }} && rustup default ${{ matrix.rust }}
- name: cargo test
run: |
cargo test --all
# Refs: https://github.com/rust-lang/cargo/issues/5657
- name: cargo check -Zminimal-versions
if: matrix.rust == 'nightly'
run: |
cargo update -Zminimal-versions
cargo check --all --all-features
style:
name: style
runs-on: ubuntu-latest
env:
RUSTFLAGS: -Dwarnings
strategy:
fail-fast: false
matrix:
component:
- clippy
- rustfmt
- rustdoc
steps:
- uses: actions/checkout@master
- name: Install Rust
run: |
rustup self update # TODO: when default rustup is bumped to 1.20+, remove this.
rustup set profile minimal
rustup update nightly && rustup default nightly
- name: Install component
if: matrix.component != 'rustdoc'
run: |
if ! rustup component add ${{ matrix.component }}; then
# If the component is unavailable on the latest nightly,
# use the latest toolchain with the component available.
# Refs: https://github.com/rust-lang/rustup-components-history#the-web-part
component=${{ matrix.component }}
target=`curl https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/$component`
echo "'$component' is unavailable on the toolchain 'nightly', use the toolchain 'nightly-$target' instead"
rustup toolchain install nightly-$target
rustup default nightly-$target
rustup component add $component
fi
- name: cargo clippy
if: matrix.component == 'clippy'
run: |
cargo clippy --all --all-features
- name: cargo fmt -- --check
if: matrix.component == 'rustfmt'
run: |
cargo fmt --all -- --check
- name: cargo doc
if: matrix.component == 'rustdoc'
run: |
cargo doc --no-deps --all --all-features
env:
RUSTDOCFLAGS: -Dwarnings
+7
View File
@@ -0,0 +1,7 @@
target
**/*.rs.bk
Cargo.lock
# For platform and editor specific settings, it is recommended to add to
# a global .gitignore file.
# Refs: https://help.github.com/en/articles/ignoring-files#create-a-global-gitignore
+19
View File
@@ -0,0 +1,19 @@
# Rustfmt configuration
# https://github.com/rust-lang/rustfmt/blob/master/Configurations.md
# This is required for bug-fixes, which technically can't be made to the stable
# first version.
version = "Two" # Tracking issue: https://github.com/rust-lang/rustfmt/issues/3383
# Refs: https://internals.rust-lang.org/t/running-rustfmt-on-rust-lang-rust-and-other-rust-lang-repositories/8732/72
use_small_heuristics = "Max"
# Apply rustfmt to more places.
merge_imports = true # Tracking issue: https://github.com/rust-lang/rustfmt/issues/3362
format_code_in_doc_comments = true # Tracking issue: https://github.com/rust-lang/rustfmt/issues/3348
# Set the default settings again to always apply the proper formatting without
# being affected by the editor settings.
# Refs: https://github.com/rust-lang/rls/issues/501#issuecomment-333717736
edition = "2018"
tab_spaces = 4
+23
View File
@@ -0,0 +1,23 @@
[package]
name = "pin-project-lite"
version = "0.1.0"
authors = ["Taiki Endo <te316e89@gmail.com>"]
edition = "2018"
license = "Apache-2.0/MIT"
repository = "https://github.com/taiki-e/pin-project-lite"
documentation = "https://docs.rs/pin-project-lite"
keywords = ["pin", "macros"]
categories = ["no-std", "rust-patterns"]
readme = "README.md"
description = """
A lightweight version of pin-project written with declarative macros.
"""
[workspace]
members = ["tests/doc"]
[dependencies]
[dev-dependencies]
rustversion = "1.0"
trybuild = "1.0"
+202
View File
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+23
View File
@@ -0,0 +1,23 @@
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
+105
View File
@@ -0,0 +1,105 @@
# 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/crates/l/pin-project-lite.svg
[license]: #license
[rustc-badge]: https://img.shields.io/badge/rustc-1.37+-lightgray.svg
[rustc-url]: https://blog.rust-lang.org/2019/08/15/Rust-1.37.0.html
A lightweight version of [pin-project] written with declarative macros.
## Usage
Add this to your `Cargo.toml`:
```toml
[dependencies]
pin-project-lite = "0.1"
```
The current pin-project-lite requires Rust 1.37 or later.
## Examples
```rust
use pin_project_lite::pin_project;
use std::pin::Pin;
pin_project! {
struct Struct<T, U> {
#[pin]
pinned: T,
unpinned: U,
}
}
impl<T, U> Struct<T, U> {
fn foo(self: Pin<&mut Self>) {
let this = self.project();
let _: Pin<&mut T> = this.pinned; // Pinned reference to the field
let _: &mut U = this.unpinned; // Normal reference to the field
}
}
```
## [pin-project] vs pin-project-lite
Here are some similarities and differences compared to [pin-project].
### Similar: Safety
pin-project-lite guarantees safety in much the same way as [pin-project]. Both are completely safe unless you write other unsafe code.
### Different: Minimal design
This library does not tackle as expansive of a range of use cases as [pin-project] does. If your use case is not already covered, please use [pin-project].
### Different: No proc-macro related dependencies
This is the **only** reason to use this crate. However, **if you already have proc-macro related dependencies in your crate's dependency graph, there is no benefit from using this crate.** (Note: There is almost no difference in the amount of code generated between [pin-project] and pin-project-lite.)
### Different: No useful error messages
This macro does not handle any invalid input. So error messages are not to be useful in most cases. If you do need useful error messages, then upon error you can pass the same input to [pin-project] to receive a line, column, and helpful description of the compile error.
### Different: Structs only
pin-project-lite will refuse anything other than a braced struct with named fields. Enums and tuple structs are not supported.
### Different: No support for custom Drop implementation
[pin-project supports this.][pinned-drop]
### Different: No support for custom Unpin implementation
[pin-project supports this.][unsafe-unpin]
### Different: No support for pattern matching and destructing
[pin-project supports this.][projection-helper]
[pin-project]: https://github.com/taiki-e/pin-project
[pinned-drop]: https://docs.rs/pin-project/0.4/pin_project/attr.pin_project.html#pinned_drop
[unsafe-unpin]: https://docs.rs/pin-project/0.4/pin_project/trait.UnsafeUnpin.html
[projection-helper]: https://docs.rs/pin-project/0.4/pin_project/attr.project.html#let-bindings
## License
Licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
+386
View File
@@ -0,0 +1,386 @@
//! A lightweight version of [pin-project] written with declarative macros.
//!
//! ## Examples
//!
//! ```rust
//! use pin_project_lite::pin_project;
//! use std::pin::Pin;
//!
//! pin_project! {
//! struct Struct<T, U> {
//! #[pin]
//! pinned: T,
//! unpinned: U,
//! }
//! }
//!
//! impl<T, U> Struct<T, U> {
//! fn foo(self: Pin<&mut Self>) {
//! let this = self.project();
//! let _: Pin<&mut T> = this.pinned; // Pinned reference to the field
//! let _: &mut U = this.unpinned; // Normal reference to the field
//! }
//! }
//! ```
//!
//! ## [pin-project] vs pin-project-lite
//!
//! Here are some similarities and differences compared to [pin-project].
//!
//! ### Similar: Safety
//!
//! pin-project-lite guarantees safety in much the same way as [pin-project]. Both are completely safe unless you write other unsafe code.
//!
//! ### Different: Minimal design
//!
//! This library does not tackle as expansive of a range of use cases as [pin-project] does. If your use case is not already covered, please use [pin-project].
//!
//! ### Different: No proc-macro related dependencies
//!
//! This is the **only** reason to use this crate. However, **if you already have proc-macro related dependencies in your crate's dependency graph, there is no benefit from using this crate.** (Note: There is almost no difference in the amount of code generated between [pin-project] and pin-project-lite.)
//!
//! ### Different: No useful error messages
//!
//! This macro does not handle any invalid input. So error messages are not to be useful in most cases. If you do need useful error messages, then upon error you can pass the same input to [pin-project] to receive a line, column, and helpful description of the compile error.
//!
//! ### Different: Structs only
//!
//! pin-project-lite will refuse anything other than a braced struct with named fields. Enums and tuple structs are not supported.
//!
//! ### Different: No support for custom Drop implementation
//!
//! [pin-project supports this.][pinned-drop]
//!
//! ### Different: No support for custom Unpin implementation
//!
//! [pin-project supports this.][unsafe-unpin]
//!
//! ### Different: No support for pattern matching and destructing
//!
//! [pin-project supports this.][projection-helper]
//!
//! [pin-project]: https://github.com/taiki-e/pin-project
//! [pinned-drop]: https://docs.rs/pin-project/0.4/pin_project/attr.pin_project.html#pinned_drop
//! [unsafe-unpin]: https://docs.rs/pin-project/0.4/pin_project/trait.UnsafeUnpin.html
//! [projection-helper]: https://docs.rs/pin-project/0.4/pin_project/attr.project.html#let-bindings
#![no_std]
#![recursion_limit = "256"]
#![doc(html_root_url = "https://docs.rs/pin-project-lite/0.1.0")]
#![doc(test(
no_crate_inject,
attr(deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code))
))]
#![warn(unsafe_code)]
#![warn(rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
#![warn(clippy::all)]
/// A macro that creates a projection struct covering all the fields.
///
/// This macro creates a projection struct according to the following rules:
///
/// - For the field that uses `#[pin]` attribute, makes the pinned reference to
/// the field.
/// - For the other fields, makes the unpinned reference to the field.
///
/// The following methods are implemented on the original type:
///
/// ```
/// # use std::pin::Pin;
/// # type Projection<'a> = &'a ();
/// # type ProjectionRef<'a> = &'a ();
/// # trait Dox {
/// fn project(self: Pin<&mut Self>) -> Projection<'_>;
/// fn project_ref(self: Pin<&Self>) -> ProjectionRef<'_>;
/// # }
/// ```
///
/// 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`.
///
/// ## Safety
///
/// `pin_project!` macro guarantees safety in much the same way as [pin-project] crate.
/// Both are completely safe unless you write other unsafe code.
///
/// See [pin-project] crate for more details.
///
/// ## Examples
///
/// ```rust
/// use pin_project_lite::pin_project;
/// use std::pin::Pin;
///
/// pin_project! {
/// struct Struct<T, U> {
/// #[pin]
/// pinned: T,
/// unpinned: U,
/// }
/// }
///
/// impl<T, U> Struct<T, U> {
/// fn foo(self: Pin<&mut Self>) {
/// let this = self.project();
/// let _: Pin<&mut T> = this.pinned; // Pinned reference to the field
/// let _: &mut U = this.unpinned; // Normal reference to the field
/// }
/// }
/// ```
///
/// Note that borrowing the field where `#[pin]` attribute is used multiple
/// times requires using [`.as_mut()`][`Pin::as_mut`] to avoid
/// consuming the `Pin`.
///
/// [pin-project]: https://github.com/taiki-e/pin-project
/// [`Pin::as_mut`]: core::pin::Pin::as_mut
#[macro_export]
macro_rules! pin_project {
(
// limitation: does not support tuple structs and enums (wontfix)
// limitation: no projection helper (wontfix)
$(#[$attrs:meta])*
$vis:vis struct $ident:ident
$(<
$( $lifetime:lifetime ),* $(,)?
// limitation: does not support multiple bounds and ? bounds.
$( $generics:ident $(: $generics_bound:path)? ),* $(,)?
>)?
$(where
// limitation: does not support multiple bounds and ? bounds.
$($where_clause_ty:ty : $where_clause_bound:path),* $(,)?
)?
{
$(
// limitation: cannot interoperate with other attributes.
$(#[$pin:ident])?
$field_vis:vis $field:ident: $field_ty:ty
),+ $(,)?
}
) => {
$(#[$attrs])*
$vis struct $ident
$(< $( $lifetime ,)* $( $generics $(: $generics_bound)? ,)* >)?
$(where
$($where_clause_ty: $where_clause_bound),*
)*
{
$(
$field_vis $field: $field_ty
),+
}
// limitation: underscore_const_names requires rust 1.37+ (wontfix)
const _: () = {
#[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
#[allow(dead_code)] // This lint warns unused fields/variants.
struct Projection
<'__pin $(, $($lifetime,)* $($generics $(: $generics_bound)? ),* )?>
$(where
$($where_clause_ty: $where_clause_bound),*
)*
{
$(
$field: $crate::pin_project!(@make_proj_field $(#[$pin])? $field_ty; mut)
),+
}
#[allow(dead_code)] // This lint warns unused fields/variants.
struct ProjectionRef
<'__pin $(, $($lifetime,)* $($generics $(: $generics_bound)? ),* )?>
$(where
$($where_clause_ty: $where_clause_bound),*
)*
{
$(
$field: $crate::pin_project!(@make_proj_field $(#[$pin])? $field_ty;)
),+
}
impl $(< $($lifetime,)* $( $generics $(: $generics_bound)? ),* >)?
$ident $(< $($lifetime,)* $($generics),* >)?
$(where
$($where_clause_ty: $where_clause_bound),*
)*
{
// limitation: does not support pub(crate) fn project (wontfix)
fn project<'__pin>(
self: ::core::pin::Pin<&'__pin mut Self>,
) -> Projection<'__pin $(, $($lifetime,)* $($generics),* )?> {
unsafe {
let this = self.get_unchecked_mut();
Projection {
$(
$field: $crate::pin_project!(@make_unsafe_field_proj this; $(#[$pin])? $field; mut)
),+
}
}
}
fn project_ref<'__pin>(
self: ::core::pin::Pin<&'__pin Self>,
) -> ProjectionRef<'__pin $(, $($lifetime,)* $($generics),* )?> {
unsafe {
let this = self.get_ref();
ProjectionRef {
$(
$field: $crate::pin_project!(@make_unsafe_field_proj this; $(#[$pin])? $field;)
),+
}
}
}
}
// Automatically create the appropriate conditional `Unpin` implementation.
//
// Basically this is equivalent to the following code:
// ```rust
// impl<T, U> Unpin for Struct<T, U> where T: Unpin {}
// ```
//
// However, if struct is public and there is a private type field,
// this would cause an E0446 (private type in public interface).
//
// When RFC 2145 is implemented (rust-lang/rust#48054),
// this will become a lint, rather then a hard error.
//
// As a workaround for this, we generate a new struct, containing all of the pinned
// fields from our #[pin_project] type. This struct is delcared within
// a function, which makes it impossible to be named by user code.
// This guarnatees that it will use the default auto-trait impl for Unpin -
// that is, it will implement Unpin iff all of its fields implement Unpin.
// This type can be safely declared as 'public', satisfiying the privacy
// checker without actually allowing user code to access it.
//
// This allows users to apply the #[pin_project] attribute to types
// regardless of the privacy of the types of their fields.
//
// See also https://github.com/taiki-e/pin-project/pull/53.
$vis struct __Origin <'__pin $(, $($lifetime,)* $($generics $(: $generics_bound)?),* )?>
$(where
$($where_clause_ty: $where_clause_bound),*
)*
{
__dummy_lifetime: ::core::marker::PhantomData<&'__pin ()>,
$(
$field: $crate::pin_project!(@make_unpin_bound $(#[$pin])? $field_ty)
),+
}
impl <'__pin $(, $($lifetime,)* $($generics $(: $generics_bound)?),* )?> ::core::marker::Unpin
for $ident $(< $($lifetime,)* $($generics),* >)?
where
__Origin <'__pin $(, $($lifetime,)* $($generics),* )?>: ::core::marker::Unpin
$(,
$($where_clause_ty: $where_clause_bound),*
)*
{
}
// Ensure that struct does not implement `Drop`.
//
// There are two possible cases:
// 1. The user type does not implement Drop. In this case,
// the first blanked impl will not apply to it. This code
// will compile, as there is only one impl of MustNotImplDrop for the user type
// 2. The user type does impl Drop. This will make the blanket impl applicable,
// which will then comflict with the explicit MustNotImplDrop impl below.
// This will result in a compilation error, which is exactly what we want.
trait MustNotImplDrop {}
#[allow(clippy::drop_bounds)]
impl<T: ::core::ops::Drop> MustNotImplDrop for T {}
#[allow(single_use_lifetimes)]
impl $(< $($lifetime,)* $($generics $(: $generics_bound)? ),*>)? MustNotImplDrop
for $ident $(< $($lifetime,)* $($generics),* >)?
$(where
$($where_clause_ty: $where_clause_bound),*
)*
{}
// Ensure that it's impossible to use pin projections on a #[repr(packed)] struct.
//
// Taking a reference to a packed field is unsafe, amd appplying
// #[deny(safe_packed_borrows)] makes sure that doing this without
// an 'unsafe' block (which we deliberately do not generate)
// is a hard error.
//
// If the struct ends up having #[repr(packed)] applied somehow,
// this will generate an (unfriendly) error message. Under all reasonable
// circumstances, we'll detect the #[repr(packed)] attribute, and generate
// a much nicer error above.
//
// See https://github.com/taiki-e/pin-project/pull/34 for more details.
#[allow(single_use_lifetimes)]
#[allow(non_snake_case)]
#[deny(safe_packed_borrows)]
fn __assert_not_repr_packed $(< $($lifetime,)* $( $generics $(: $generics_bound)? ),* >)? (
this: &$ident $(< $($generics),* >)?
)
$(where
$($where_clause_ty: $where_clause_bound),*
)*
{
$(
&this.$field;
)+
}
};
};
// make_unpin_bound
(@make_unpin_bound
#[pin]
$field_ty:ty
) => {
$field_ty
};
(@make_unpin_bound
$field_ty:ty
) => {
$crate::__private::AlwaysUnpin<$field_ty>
};
// make_unsafe_field_proj
(@make_unsafe_field_proj
$this:ident;
#[pin]
$field:ident;
$($mut:ident)?
) => {
::core::pin::Pin::new_unchecked(&$($mut)? $this.$field)
};
(@make_unsafe_field_proj
$this:ident;
$field:ident;
$($mut:ident)?
) => {
&$($mut)? $this.$field
};
// make_proj_field
(@make_proj_field
#[pin]
$field_ty:ty;
$($mut:ident)?
) => {
::core::pin::Pin<&'__pin $($mut)? ($field_ty)>
};
(@make_proj_field
$field_ty:ty;
$($mut:ident)?
) => {
&'__pin $($mut)? ($field_ty)
};
// limitation: no useful error messages (wontfix)
}
// Not public API.
#[doc(hidden)]
pub mod __private {
use core::marker::PhantomData;
// This is an internal helper struct used by `pin_project!`.
#[doc(hidden)]
pub struct AlwaysUnpin<T: ?Sized>(PhantomData<T>);
impl<T: ?Sized> Unpin for AlwaysUnpin<T> {}
}
+9
View File
@@ -0,0 +1,9 @@
#![warn(unsafe_code)]
#![warn(rust_2018_idioms, single_use_lifetimes)]
#[rustversion::attr(not(nightly), ignore)]
#[test]
fn ui() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/ui/*.rs");
}
+11
View File
@@ -0,0 +1,11 @@
[package]
name = "doctest"
version = "0.1.0"
authors = ["Taiki Endo <te316e89@gmail.com>"]
edition = "2018"
publish = false
[dependencies]
[dev-dependencies]
pin-project-lite = { path = "../.." }
+19
View File
@@ -0,0 +1,19 @@
#![warn(unsafe_code)]
#![warn(rust_2018_idioms, single_use_lifetimes)]
use std::{env, process::Command};
fn main() {
println!("cargo:rerun-if-changed=build.rs");
if is_nightly() {
println!("cargo:rustc-cfg=nightly");
}
}
fn is_nightly() -> bool {
env::var_os("RUSTC")
.and_then(|rustc| Command::new(rustc).arg("--version").output().ok())
.and_then(|output| String::from_utf8(output.stdout).ok())
.map_or(false, |version| version.contains("nightly") || version.contains("dev"))
}
+15
View File
@@ -0,0 +1,15 @@
#![cfg(nightly)]
#![doc(test(
no_crate_inject,
attr(deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code))
))]
#![feature(external_doc)]
// As `external_doc` and `doc-comment` do not work with `cfg(test)`,
// these tests are split into this crate.
// Refs:
// * https://github.com/rust-lang/rust/issues/62210
// * https://github.com/rust-lang/rust/pull/63803
#[doc(include = "../../../README.md")]
const _README: () = ();
+272
View File
@@ -0,0 +1,272 @@
#![no_std]
#![warn(unsafe_code)]
#![warn(rust_2018_idioms, single_use_lifetimes)]
#![allow(dead_code)]
use core::{marker::PhantomPinned, pin::Pin};
use pin_project_lite::pin_project;
#[test]
fn test_pin_project() {
pin_project! {
struct Foo<T, U> {
#[pin]
field1: T,
field2: U,
}
}
let mut foo = Foo { field1: 1, field2: 2 };
let mut foo_orig = Pin::new(&mut foo);
let foo = foo_orig.as_mut().project();
let x: Pin<&mut i32> = foo.field1;
assert_eq!(*x, 1);
let y: &mut i32 = foo.field2;
assert_eq!(*y, 2);
assert_eq!(foo_orig.as_ref().field1, 1);
assert_eq!(foo_orig.as_ref().field2, 2);
let mut foo = Foo { field1: 1, field2: 2 };
let foo = Pin::new(&mut foo).project();
let field1 = foo.field1;
let field2 = foo.field2;
let _: Pin<&mut i32> = field1;
let _: &mut i32 = field2;
}
#[test]
fn where_clause_and_associated_type_fields() {
pin_project! {
struct Struct1<I>
where
I: Iterator,
{
#[pin]
field1: I,
field2: I::Item,
}
}
pin_project! {
struct Struct2<I, J>
where
I: Iterator<Item = J>,
{
#[pin]
field1: I,
field2: J,
}
}
}
#[test]
fn derive_copy() {
pin_project! {
#[derive(Clone, Copy)]
struct Struct<T> {
val: T,
}
}
fn is_copy<T: Copy>() {}
is_copy::<Struct<u8>>();
}
#[test]
fn move_out() {
struct NotCopy;
pin_project! {
struct Struct {
val: NotCopy,
}
}
let foo = Struct { val: NotCopy };
let _val: NotCopy = foo.val;
}
#[test]
fn trait_bounds_on_type_generics() {
// pin_project! {
// pub struct Struct1<'a, T: ?Sized> {
// field: &'a mut T,
// }
// }
pin_project! {
pub struct Struct2<'a, T: ::core::fmt::Debug> {
field: &'a mut T,
}
}
pin_project! {
pub struct Struct3<'a, T: core::fmt::Debug> {
field: &'a mut T,
}
}
// pin_project! {
// pub struct Struct4<'a, T: core::fmt::Debug + core::fmt::Display> {
// field: &'a mut T,
// }
// }
// pin_project! {
// pub struct Struct5<'a, T: core::fmt::Debug + ?Sized> {
// field: &'a mut T,
// }
// }
}
#[test]
fn private_type_in_public_type() {
pin_project! {
pub struct PublicStruct<T> {
#[pin]
inner: PrivateStruct<T>,
}
}
struct PrivateStruct<T>(T);
}
#[test]
fn lifetime_project() {
pin_project! {
struct Struct1<T, U> {
#[pin]
pinned: T,
unpinned: U,
}
}
pin_project! {
struct Struct2<'a, T, U> {
#[pin]
pinned: &'a mut T,
unpinned: U,
}
}
impl<T, U> Struct1<T, U> {
fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a T> {
self.project_ref().pinned
}
fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut T> {
self.project().pinned
}
}
impl<'b, T, U> Struct2<'b, T, U> {
fn get_pin_ref<'a>(self: Pin<&'a Self>) -> Pin<&'a &'b mut T> {
self.project_ref().pinned
}
fn get_pin_mut<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut &'b mut T> {
self.project().pinned
}
}
}
#[test]
fn lifetime_project_elided() {
pin_project! {
struct Struct1<T, U> {
#[pin]
pinned: T,
unpinned: U,
}
}
pin_project! {
struct Struct2<'a, T, U> {
#[pin]
pinned: &'a mut T,
unpinned: U,
}
}
impl<T, U> Struct1<T, U> {
fn get_pin_ref(self: Pin<&Self>) -> Pin<&T> {
self.project_ref().pinned
}
fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
self.project().pinned
}
}
impl<'b, T, U> Struct2<'b, T, U> {
fn get_pin_ref(self: Pin<&Self>) -> Pin<&&'b mut T> {
self.project_ref().pinned
}
fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut &'b mut T> {
self.project().pinned
}
}
}
#[test]
fn trivial_bounds() {
pin_project! {
pub struct NoGenerics {
#[pin]
field: PhantomPinned,
}
}
}
// #[test]
// fn dst() {
// pin_project! {
// pub struct A<T: ?Sized> {
// x: T,
// }
// }
// pin_project! {
// pub struct B<T: ?Sized> {
// #[pin]
// x: T,
// }
// }
// }
#[test]
fn dyn_type() {
pin_project! {
struct Struct1 {
a: i32,
f: dyn core::fmt::Debug,
}
}
pin_project! {
struct Struct2 {
a: i32,
#[pin]
f: dyn core::fmt::Debug,
}
}
pin_project! {
struct Struct3 {
a: i32,
f: dyn core::fmt::Debug + Send,
}
}
pin_project! {
struct Struct4 {
a: i32,
#[pin]
f: dyn core::fmt::Debug + Send,
}
}
}
+15
View File
@@ -0,0 +1,15 @@
use pin_project_lite::pin_project;
pin_project! { //~ ERROR E0119
struct Foo<T, U> {
#[pin]
future: T,
field: U,
}
}
impl<T, U> Drop for Foo<T, U> {
fn drop(&mut self) {}
}
fn main() {}
+16
View File
@@ -0,0 +1,16 @@
error[E0119]: conflicting implementations of trait `_::MustNotImplDrop` for type `Foo<_, _>`:
--> $DIR/conflict-drop.rs:3:1
|
3 | / pin_project! { //~ ERROR E0119
4 | | struct Foo<T, U> {
5 | | #[pin]
6 | | future: T,
7 | | field: U,
8 | | }
9 | | }
| | ^
| | |
| |_first implementation here
| conflicting implementation for `Foo<_, _>`
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+40
View File
@@ -0,0 +1,40 @@
use pin_project_lite::pin_project;
// The same implementation.
pin_project! { //~ ERROR E0119
struct Foo<T, U> {
#[pin]
future: T,
field: U,
}
}
// conflicting implementations
impl<T, U> Unpin for Foo<T, U> where T: Unpin {} // Conditional Unpin impl
// The implementation that under different conditions.
pin_project! { //~ ERROR E0119
struct Bar<T, U> {
#[pin]
future: T,
field: U,
}
}
// conflicting implementations
impl<T, U> Unpin for Bar<T, U> {} // Non-conditional Unpin impl
pin_project! { //~ ERROR E0119
struct Baz<T, U> {
#[pin]
future: T,
field: U,
}
}
// conflicting implementations
impl<T: Unpin, U: Unpin> Unpin for Baz<T, U> {} // Conditional Unpin impl
fn main() {}
+50
View File
@@ -0,0 +1,50 @@
error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Foo<_, _>`:
--> $DIR/conflict-unpin.rs:5:1
|
5 | / pin_project! { //~ ERROR E0119
6 | | struct Foo<T, U> {
7 | | #[pin]
8 | | future: T,
9 | | field: U,
10 | | }
11 | | }
| |_^ conflicting implementation for `Foo<_, _>`
...
14 | impl<T, U> Unpin for Foo<T, U> where T: Unpin {} // Conditional Unpin impl
| --------------------------------------------- first implementation here
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Bar<_, _>`:
--> $DIR/conflict-unpin.rs:18:1
|
18 | / pin_project! { //~ ERROR E0119
19 | | struct Bar<T, U> {
20 | | #[pin]
21 | | future: T,
22 | | field: U,
23 | | }
24 | | }
| |_^ conflicting implementation for `Bar<_, _>`
...
27 | impl<T, U> Unpin for Bar<T, U> {} // Non-conditional Unpin impl
| ------------------------------ first implementation here
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0119]: conflicting implementations of trait `std::marker::Unpin` for type `Baz<_, _>`:
--> $DIR/conflict-unpin.rs:29:1
|
29 | / pin_project! { //~ ERROR E0119
30 | | struct Baz<T, U> {
31 | | #[pin]
32 | | future: T,
33 | | field: U,
34 | | }
35 | | }
| |_^ conflicting implementation for `Baz<_, _>`
...
38 | impl<T: Unpin, U: Unpin> Unpin for Baz<T, U> {} // Conditional Unpin impl
| -------------------------------------------- first implementation here
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+25
View File
@@ -0,0 +1,25 @@
use pin_project_lite::pin_project;
pin_project! {
struct A<T> {
#[pin()] //~ ERROR no rules expected the token `(`
pinned: T,
}
}
pin_project! {
#[pin] //~ ERROR cannot find attribute `pin` in this scope
struct B<T> {
pinned: T,
}
}
pin_project! {
struct C<T> {
#[pin]
#[pin] //~ ERROR no rules expected the token `#`
pinned: T,
}
}
fn main() {}
+17
View File
@@ -0,0 +1,17 @@
error: no rules expected the token `(`
--> $DIR/invalid.rs:5:14
|
5 | #[pin()] //~ ERROR no rules expected the token `(`
| ^ no rules expected this token in macro call
error: no rules expected the token `#`
--> $DIR/invalid.rs:20:9
|
20 | #[pin] //~ ERROR no rules expected the token `#`
| ^ no rules expected this token in macro call
error: cannot find attribute `pin` in this scope
--> $DIR/invalid.rs:11:7
|
11 | #[pin] //~ ERROR cannot find attribute `pin` in this scope
| ^^^
+10
View File
@@ -0,0 +1,10 @@
use pin_project_lite::pin_project;
pin_project! { //~ ERROR E0496
pub struct Foo<'__pin, T> { //~ ERROR E0263
#[pin]
field: &'__pin mut T,
}
}
fn main() {}
@@ -0,0 +1,83 @@
error[E0263]: lifetime name `'__pin` declared twice in the same scope
--> $DIR/overlapping_lifetime_names.rs:4:20
|
3 | / pin_project! { //~ ERROR E0496
4 | | pub struct Foo<'__pin, T> { //~ ERROR E0263
| | ^^^^^^ declared twice
5 | | #[pin]
6 | | field: &'__pin mut T,
7 | | }
8 | | }
| |_- previous declaration here
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0263]: lifetime name `'__pin` declared twice in the same scope
--> $DIR/overlapping_lifetime_names.rs:4:20
|
3 | / pin_project! { //~ ERROR E0496
4 | | pub struct Foo<'__pin, T> { //~ ERROR E0263
| | ^^^^^^ declared twice
5 | | #[pin]
6 | | field: &'__pin mut T,
7 | | }
8 | | }
| |_- previous declaration here
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0496]: lifetime name `'__pin` shadows a lifetime name that is already in scope
--> $DIR/overlapping_lifetime_names.rs:3:1
|
3 | / pin_project! { //~ ERROR E0496
4 | | pub struct Foo<'__pin, T> { //~ ERROR E0263
| | ------ first declared here
5 | | #[pin]
6 | | field: &'__pin mut T,
7 | | }
8 | | }
| |_^ lifetime '__pin already in scope
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0496]: lifetime name `'__pin` shadows a lifetime name that is already in scope
--> $DIR/overlapping_lifetime_names.rs:3:1
|
3 | / pin_project! { //~ ERROR E0496
4 | | pub struct Foo<'__pin, T> { //~ ERROR E0263
| | ------ first declared here
5 | | #[pin]
6 | | field: &'__pin mut T,
7 | | }
8 | | }
| |_^ lifetime '__pin already in scope
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0263]: lifetime name `'__pin` declared twice in the same scope
--> $DIR/overlapping_lifetime_names.rs:4:20
|
3 | / pin_project! { //~ ERROR E0496
4 | | pub struct Foo<'__pin, T> { //~ ERROR E0263
| | ^^^^^^ declared twice
5 | | #[pin]
6 | | field: &'__pin mut T,
7 | | }
8 | | }
| |_- previous declaration here
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0263]: lifetime name `'__pin` declared twice in the same scope
--> $DIR/overlapping_lifetime_names.rs:4:20
|
3 | / pin_project! { //~ ERROR E0496
4 | | pub struct Foo<'__pin, T> { //~ ERROR E0263
| | ^^^^^^ declared twice
5 | | #[pin]
6 | | field: &'__pin mut T,
7 | | }
8 | | }
| |_- previous declaration here
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+19
View File
@@ -0,0 +1,19 @@
use pin_project_lite::pin_project;
use std::marker::PhantomPinned;
pin_project! {
struct Foo<T> {
#[pin]
inner: T,
}
}
struct __Origin {}
impl Unpin for __Origin {}
fn is_unpin<T: Unpin>() {}
fn main() {
is_unpin::<Foo<PhantomPinned>>(); //~ ERROR E0277
}
+13
View File
@@ -0,0 +1,13 @@
error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` is not satisfied in `_::__Origin<'_, std::marker::PhantomPinned>`
--> $DIR/overlapping_unpin_struct.rs:18:5
|
15 | fn is_unpin<T: Unpin>() {}
| -------- ----- required by this bound in `is_unpin`
...
18 | is_unpin::<Foo<PhantomPinned>>(); //~ ERROR E0277
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `_::__Origin<'_, std::marker::PhantomPinned>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned`
|
= help: the following implementations were found:
<std::marker::PhantomPinned as std::marker::Unpin>
= note: required because it appears within the type `_::__Origin<'_, std::marker::PhantomPinned>`
= note: required because of the requirements on the impl of `std::marker::Unpin` for `Foo<std::marker::PhantomPinned>`
+19
View File
@@ -0,0 +1,19 @@
use pin_project_lite::pin_project;
pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
#[repr(packed, C)]
struct A {
#[pin]
field: u16,
}
}
pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
#[repr(packed(2))]
struct C {
#[pin]
field: u32,
}
}
fn main() {}
+55
View File
@@ -0,0 +1,55 @@
error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
--> $DIR/packed.rs:3:1
|
3 | / pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
4 | | #[repr(packed, C)]
5 | | struct A {
6 | | #[pin]
7 | | field: u16,
8 | | }
9 | | }
| |_^
|
note: lint level defined here
--> $DIR/packed.rs:3:1
|
3 | / pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
4 | | #[repr(packed, C)]
5 | | struct A {
6 | | #[pin]
7 | | field: u16,
8 | | }
9 | | }
| |_^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
= note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
--> $DIR/packed.rs:11:1
|
11 | / pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
12 | | #[repr(packed(2))]
13 | | struct C {
14 | | #[pin]
15 | | field: u32,
16 | | }
17 | | }
| |_^
|
note: lint level defined here
--> $DIR/packed.rs:11:1
|
11 | / pin_project! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
12 | | #[repr(packed(2))]
13 | | struct C {
14 | | #[pin]
15 | | field: u32,
16 | | }
17 | | }
| |_^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
= note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+41
View File
@@ -0,0 +1,41 @@
use pin_project_lite::pin_project;
use std::marker::PhantomPinned;
struct Inner<T> {
val: T,
}
pin_project! {
struct Foo<T, U> {
#[pin]
inner: Inner<T>,
other: U,
}
}
pin_project! {
pub struct TrivialBounds {
#[pin]
field1: PhantomPinned,
}
}
pin_project! {
struct Bar<'a, T, U> {
#[pin]
inner: &'a mut Inner<T>,
other: U,
}
}
fn is_unpin<T: Unpin>() {}
fn main() {
is_unpin::<Foo<PhantomPinned, ()>>(); //~ ERROR E0277
is_unpin::<Foo<(), PhantomPinned>>(); // Ok
is_unpin::<Foo<PhantomPinned, PhantomPinned>>(); //~ ERROR E0277
is_unpin::<TrivialBounds>(); //~ ERROR E0277
is_unpin::<Bar<'_, PhantomPinned, PhantomPinned>>(); //~ Ok
}
+43
View File
@@ -0,0 +1,43 @@
error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` is not satisfied in `_::__Origin<'_, std::marker::PhantomPinned, ()>`
--> $DIR/proper_unpin.rs:34:5
|
31 | fn is_unpin<T: Unpin>() {}
| -------- ----- required by this bound in `is_unpin`
...
34 | is_unpin::<Foo<PhantomPinned, ()>>(); //~ ERROR E0277
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `_::__Origin<'_, std::marker::PhantomPinned, ()>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned`
|
= help: the following implementations were found:
<std::marker::PhantomPinned as std::marker::Unpin>
= note: required because it appears within the type `Inner<std::marker::PhantomPinned>`
= note: required because it appears within the type `_::__Origin<'_, std::marker::PhantomPinned, ()>`
= note: required because of the requirements on the impl of `std::marker::Unpin` for `Foo<std::marker::PhantomPinned, ()>`
error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` is not satisfied in `_::__Origin<'_, std::marker::PhantomPinned, std::marker::PhantomPinned>`
--> $DIR/proper_unpin.rs:36:5
|
31 | fn is_unpin<T: Unpin>() {}
| -------- ----- required by this bound in `is_unpin`
...
36 | is_unpin::<Foo<PhantomPinned, PhantomPinned>>(); //~ ERROR E0277
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `_::__Origin<'_, std::marker::PhantomPinned, std::marker::PhantomPinned>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned`
|
= help: the following implementations were found:
<std::marker::PhantomPinned as std::marker::Unpin>
= note: required because it appears within the type `Inner<std::marker::PhantomPinned>`
= note: required because it appears within the type `_::__Origin<'_, std::marker::PhantomPinned, std::marker::PhantomPinned>`
= note: required because of the requirements on the impl of `std::marker::Unpin` for `Foo<std::marker::PhantomPinned, std::marker::PhantomPinned>`
error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` is not satisfied in `_::__Origin<'_>`
--> $DIR/proper_unpin.rs:38:5
|
31 | fn is_unpin<T: Unpin>() {}
| -------- ----- required by this bound in `is_unpin`
...
38 | is_unpin::<TrivialBounds>(); //~ ERROR E0277
| ^^^^^^^^^^^^^^^^^^^^^^^^^ within `_::__Origin<'_>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned`
|
= help: the following implementations were found:
<std::marker::PhantomPinned as std::marker::Unpin>
= note: required because it appears within the type `_::__Origin<'_>`
= note: required because of the requirements on the impl of `std::marker::Unpin` for `TrivialBounds`
+12
View File
@@ -0,0 +1,12 @@
use pin_project_lite::pin_project;
pin_project! {
struct Foo {
#[pin]
inner: u8,
}
}
impl Unpin for __Origin {} //~ ERROR E0412,E0321
fn main() {}
+11
View File
@@ -0,0 +1,11 @@
error[E0412]: cannot find type `__Origin` in this scope
--> $DIR/unpin_sneaky.rs:10:16
|
10 | impl Unpin for __Origin {} //~ ERROR E0412,E0321
| ^^^^^^^^ not found in this scope
error[E0321]: cross-crate traits with a default impl, like `std::marker::Unpin`, can only be implemented for a struct/enum type, not `[type error]`
--> $DIR/unpin_sneaky.rs:10:1
|
10 | impl Unpin for __Origin {} //~ ERROR E0412,E0321
| ^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
+27
View File
@@ -0,0 +1,27 @@
use pin_project_lite::pin_project;
pin_project! {
struct Struct1 {} //~ ERROR no rules expected the token `}`
}
pin_project! {
struct Struct2(); //~ ERROR no rules expected the token `(`
}
pin_project! {
struct Struct3; //~ ERROR no rules expected the token `;`
}
pin_project! {
enum Enum { //~ ERROR no rules expected the token `enum`
A(u8)
}
}
pin_project! {
union Union { //~ ERROR no rules expected the token `union`
x: u8,
}
}
fn main() {}
+29
View File
@@ -0,0 +1,29 @@
error: no rules expected the token `}`
--> $DIR/unsupported.rs:4:21
|
4 | struct Struct1 {} //~ ERROR no rules expected the token `}`
| ^ no rules expected this token in macro call
error: no rules expected the token `(`
--> $DIR/unsupported.rs:8:19
|
8 | struct Struct2(); //~ ERROR no rules expected the token `(`
| ^ no rules expected this token in macro call
error: no rules expected the token `;`
--> $DIR/unsupported.rs:12:19
|
12 | struct Struct3; //~ ERROR no rules expected the token `;`
| ^ no rules expected this token in macro call
error: no rules expected the token `enum`
--> $DIR/unsupported.rs:16:5
|
16 | enum Enum { //~ ERROR no rules expected the token `enum`
| ^^^^ no rules expected this token in macro call
error: no rules expected the token `union`
--> $DIR/unsupported.rs:22:5
|
22 | union Union { //~ ERROR no rules expected the token `union`
| ^^^^^ no rules expected this token in macro call