summaryrefslogtreecommitdiffstats
path: root/third_party/rust/pin-project-internal
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/pin-project-internal')
-rw-r--r--third_party/rust/pin-project-internal/.cargo-checksum.json1
-rw-r--r--third_party/rust/pin-project-internal/Cargo.toml36
-rw-r--r--third_party/rust/pin-project-internal/LICENSE-APACHE202
-rw-r--r--third_party/rust/pin-project-internal/LICENSE-MIT23
-rw-r--r--third_party/rust/pin-project-internal/src/lib.rs552
-rw-r--r--third_party/rust/pin-project-internal/src/pin_project/attribute.rs71
-rw-r--r--third_party/rust/pin-project-internal/src/pin_project/derive.rs834
-rw-r--r--third_party/rust/pin-project-internal/src/pin_project/mod.rs15
-rw-r--r--third_party/rust/pin-project-internal/src/pinned_drop.rs199
-rw-r--r--third_party/rust/pin-project-internal/src/project.rs286
-rw-r--r--third_party/rust/pin-project-internal/src/utils.rs339
11 files changed, 2558 insertions, 0 deletions
diff --git a/third_party/rust/pin-project-internal/.cargo-checksum.json b/third_party/rust/pin-project-internal/.cargo-checksum.json
new file mode 100644
index 0000000000..a115ec6566
--- /dev/null
+++ b/third_party/rust/pin-project-internal/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"3fe6c53bc8cb8dfee1091ff799a743024b78bbf7ded986396ccb8a139bc7f02b","LICENSE-APACHE":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","src/lib.rs":"fe9fdaa1dcf2e9ade6ae1c34e20195223c8f63d19c0ba2d0189e07207d4f1a30","src/pin_project/attribute.rs":"5b441bab16d19215d660790b46eab18b402d36edb951ba7f8284772bf2a470bd","src/pin_project/derive.rs":"f244d4bed929350fdfcc96513fce17a4ab2146e1f7974ae1255d72a9b72ffd33","src/pin_project/mod.rs":"4c5f5215d1737a6e4797d7f5eb1f7f6008505b06cfc304a66758bd96e6252c0c","src/pinned_drop.rs":"4519a66e9804143578faf60ed8239811d92cc6b2af817736439a9bc772d48780","src/project.rs":"e6ce9acaaad85d9945c24ec4507e6373aa61dfab50717453666733fa8161c099","src/utils.rs":"340a79dd4b02b5ea97c747ef5c56d5a8cedfaeff4a259fe5140c83803b2ed115"},"package":"8988430ce790d8682672117bc06dda364c0be32d3abd738234f19f3240bad99a"} \ No newline at end of file
diff --git a/third_party/rust/pin-project-internal/Cargo.toml b/third_party/rust/pin-project-internal/Cargo.toml
new file mode 100644
index 0000000000..f9d79ef0e9
--- /dev/null
+++ b/third_party/rust/pin-project-internal/Cargo.toml
@@ -0,0 +1,36 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "pin-project-internal"
+version = "0.4.9"
+authors = ["Taiki Endo <te316e89@gmail.com>"]
+description = "An internal crate to support pin_project - do not use directly\n"
+homepage = "https://github.com/taiki-e/pin-project"
+documentation = "https://docs.rs/pin-project-internal"
+keywords = ["pin", "macros", "attribute"]
+categories = ["no-std", "rust-patterns"]
+license = "Apache-2.0 OR MIT"
+repository = "https://github.com/taiki-e/pin-project"
+
+[lib]
+proc-macro = true
+[dependencies.proc-macro2]
+version = "1.0"
+
+[dependencies.quote]
+version = "1.0"
+
+[dependencies.syn]
+version = "1.0"
+features = ["full", "visit-mut"]
diff --git a/third_party/rust/pin-project-internal/LICENSE-APACHE b/third_party/rust/pin-project-internal/LICENSE-APACHE
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/third_party/rust/pin-project-internal/LICENSE-APACHE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/third_party/rust/pin-project-internal/LICENSE-MIT b/third_party/rust/pin-project-internal/LICENSE-MIT
new file mode 100644
index 0000000000..31aa79387f
--- /dev/null
+++ b/third_party/rust/pin-project-internal/LICENSE-MIT
@@ -0,0 +1,23 @@
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/pin-project-internal/src/lib.rs b/third_party/rust/pin-project-internal/src/lib.rs
new file mode 100644
index 0000000000..ba7abbb3d4
--- /dev/null
+++ b/third_party/rust/pin-project-internal/src/lib.rs
@@ -0,0 +1,552 @@
+//! An internal crate to support pin_project - **do not use directly**
+
+#![recursion_limit = "256"]
+#![doc(html_root_url = "https://docs.rs/pin-project-internal/0.4.9")]
+#![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)]
+// mem::take requires Rust 1.40
+#![allow(clippy::mem_replace_with_default)]
+#![allow(clippy::needless_doctest_main)]
+// While this crate supports stable Rust, it currently requires
+// nightly Rust in order for rustdoc to correctly document auto-generated
+// `Unpin` impls. This does not affect the runtime functionality of this crate,
+// nor does it affect the safety of the api provided by this crate.
+//
+// This is disabled by default and can be enabled using
+// `--cfg pin_project_show_unpin_struct` in RUSTFLAGS.
+//
+// Refs:
+// * https://github.com/taiki-e/pin-project/pull/53#issuecomment-525906867
+// * https://github.com/taiki-e/pin-project/pull/70
+// * https://github.com/rust-lang/rust/issues/63281
+#![cfg_attr(pin_project_show_unpin_struct, feature(proc_macro_def_site))]
+
+// older compilers require explicit `extern crate`.
+#[allow(unused_extern_crates)]
+extern crate proc_macro;
+
+#[macro_use]
+mod utils;
+
+mod pin_project;
+mod pinned_drop;
+mod project;
+
+use proc_macro::TokenStream;
+
+use utils::{Immutable, Mutable};
+
+/// An attribute that creates a projection struct covering all the fields.
+///
+/// This attribute 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 `#[pin_project]` type:
+///
+/// ```
+/// # #[rustversion::since(1.36)]
+/// # fn dox() {
+/// # use std::pin::Pin;
+/// # type Projection<'a> = &'a ();
+/// # type ProjectionRef<'a> = &'a ();
+/// # trait Dox {
+/// fn project(self: Pin<&mut Self>) -> Projection<'_>;
+/// fn project_ref(self: Pin<&Self>) -> ProjectionRef<'_>;
+/// # }
+/// # }
+/// ```
+///
+/// The visibility of the projected type and projection method is based on the
+/// original type. However, if the visibility of the original type is `pub`,
+/// the visibility of the projected type and the projection method is `pub(crate)`.
+///
+/// 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
+///
+/// This attribute is completely safe. In the absence of other `unsafe` code *that you write*,
+/// it is impossible to cause undefined behavior with this attribute.
+///
+/// This is accomplished by enforcing the four requirements for pin projection
+/// stated in [the Rust documentation](https://doc.rust-lang.org/nightly/std/pin/index.html#projections-and-structural-pinning):
+///
+/// 1. The struct must only be Unpin if all the structural fields are Unpin.
+///
+/// To enforce this, this attribute will automatically generate an `Unpin` implementation
+/// for you, which will require that all structurally pinned fields be `Unpin`
+/// If you wish to provide an manual `Unpin` impl, you can do so via the
+/// `UnsafeUnpin` argument.
+///
+/// 2. The destructor of the struct must not move structural fields out of its argument.
+///
+/// To enforce this, this attribute will generate code like this:
+///
+/// ```rust
+/// struct MyStruct {}
+/// trait MyStructMustNotImplDrop {}
+/// impl<T: Drop> MyStructMustNotImplDrop for T {}
+/// impl MyStructMustNotImplDrop for MyStruct {}
+/// ```
+///
+/// If you attempt to provide an Drop impl, the blanket impl will
+/// then apply to your type, causing a compile-time error due to
+/// the conflict with the second impl.
+///
+/// If you wish to provide a custom `Drop` impl, you can annotate a function
+/// with `#[pinned_drop]`. This function takes a pinned version of your struct -
+/// that is, `Pin<&mut MyStruct>` where `MyStruct` is the type of your struct.
+///
+/// You can call `project()` on this type as usual, along with any other
+/// methods you have defined. Because your code is never provided with
+/// a `&mut MyStruct`, it is impossible to move out of pin-projectable
+/// fields in safe code in your destructor.
+///
+/// 3. You must make sure that you uphold the Drop guarantee: once your struct is pinned,
+/// the memory that contains the content is not overwritten or deallocated without calling the content's destructors.
+///
+/// Safe code doesn't need to worry about this - the only wait to violate this requirement
+/// is to manually deallocate memory (which is `unsafe`), or to overwrite a field with something else.
+/// Because your custom destructor takes `Pin<&mut MyStruct`, it's impossible to obtain
+/// a mutable reference to a pin-projected field in safe code.
+///
+/// 4. You must not offer any other operations that could lead to data being moved out of the structural fields when your type is pinned.
+///
+/// As with requirement 3, it is impossible for safe code to violate this. This crate ensures that safe code can never
+/// obtain a mutable reference to `#[pin]` fields, which prevents you from ever moving out of them in safe code.
+///
+/// Pin projections are also incompatible with `#[repr(packed)]` structs. Attempting to use this attribute
+/// on a `#[repr(packed)]` struct results in a compile-time error.
+///
+///
+/// ## Examples
+///
+/// Using `#[pin_project]` will automatically create the appropriate
+/// conditional [`Unpin`] implementation:
+///
+/// ```rust
+/// use pin_project::pin_project;
+/// use std::pin::Pin;
+///
+/// #[pin_project]
+/// struct Foo<T, U> {
+/// #[pin]
+/// future: T,
+/// field: U,
+/// }
+///
+/// impl<T, U> Foo<T, U> {
+/// fn baz(self: Pin<&mut Self>) {
+/// let this = self.project();
+/// let _: Pin<&mut T> = this.future; // Pinned reference to the field
+/// let _: &mut U = this.field; // 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`.
+///
+/// If you want to implement [`Unpin`] manually, you must use the `UnsafeUnpin`
+/// argument to `#[pin_project]`.
+///
+/// ```rust
+/// use pin_project::{pin_project, UnsafeUnpin};
+/// use std::pin::Pin;
+///
+/// #[pin_project(UnsafeUnpin)]
+/// struct Foo<T, U> {
+/// #[pin]
+/// future: T,
+/// field: U,
+/// }
+///
+/// impl<T, U> Foo<T, U> {
+/// fn baz(self: Pin<&mut Self>) {
+/// let this = self.project();
+/// let _: Pin<&mut T> = this.future; // Pinned reference to the field
+/// let _: &mut U = this.field; // Normal reference to the field
+/// }
+/// }
+///
+/// unsafe impl<T: Unpin, U> UnsafeUnpin for Foo<T, U> {} // Conditional Unpin impl
+/// ```
+///
+/// Note the usage of the unsafe [`UnsafeUnpin`] trait, instead of the usual
+/// [`Unpin`] trait. [`UnsafeUnpin`] behaves exactly like [`Unpin`], except that is
+/// unsafe to implement. This unsafety comes from the fact that pin projections
+/// are being used. If you implement [`UnsafeUnpin`], you must ensure that it is
+/// only implemented when all pin-projected fields implement [`Unpin`].
+///
+/// See [`UnsafeUnpin`] trait for more details.
+///
+/// ### `#[pinned_drop]`
+///
+/// In order to correctly implement pin projections, a type's `Drop` impl must
+/// not move out of any structurally pinned fields. Unfortunately, [`Drop::drop`]
+/// takes `&mut Self`, not `Pin<&mut Self>`.
+///
+/// To ensure that this requirement is upheld, the `#[pin_project]` attribute will
+/// provide a [`Drop`] impl for you. This `Drop` impl will delegate to an impl
+/// block annotated with `#[pinned_drop]` if you use the `PinnedDrop` argument
+/// to `#[pin_project]`. This impl block acts just like a normal [`Drop`] impl,
+/// except for the following two:
+///
+/// * `drop` method takes `Pin<&mut Self>`
+/// * Name of the trait is `PinnedDrop`.
+///
+/// `#[pin_project]` implements the actual [`Drop`] trait via `PinnedDrop` you
+/// implemented. To drop a type that implements `PinnedDrop`, use the [`drop`]
+/// function just like dropping a type that directly implements [`Drop`].
+///
+/// In particular, it will never be called more than once, just like [`Drop::drop`].
+///
+/// For example:
+///
+/// ```rust
+/// use pin_project::{pin_project, pinned_drop};
+/// use std::{fmt::Debug, pin::Pin};
+///
+/// #[pin_project(PinnedDrop)]
+/// pub struct Foo<T: Debug, U: Debug> {
+/// #[pin]
+/// pinned_field: T,
+/// unpin_field: U,
+/// }
+///
+/// #[pinned_drop]
+/// impl<T: Debug, U: Debug> PinnedDrop for Foo<T, U> {
+/// fn drop(self: Pin<&mut Self>) {
+/// println!("Dropping pinned field: {:?}", self.pinned_field);
+/// println!("Dropping unpin field: {:?}", self.unpin_field);
+/// }
+/// }
+///
+/// fn main() {
+/// let _x = Foo { pinned_field: true, unpin_field: 40 };
+/// }
+/// ```
+///
+/// See also [`pinned_drop`] attribute.
+///
+/// ## Supported Items
+///
+/// The current pin-project supports the following types of items.
+///
+/// ### Structs (structs with named fields):
+///
+/// ```rust
+/// use pin_project::pin_project;
+/// use std::pin::Pin;
+///
+/// #[pin_project]
+/// struct Foo<T, U> {
+/// #[pin]
+/// future: T,
+/// field: U,
+/// }
+///
+/// impl<T, U> Foo<T, U> {
+/// fn baz(self: Pin<&mut Self>) {
+/// let this = self.project();
+/// let _: Pin<&mut T> = this.future;
+/// let _: &mut U = this.field;
+/// }
+/// }
+/// ```
+///
+/// ### Tuple structs (structs with unnamed fields):
+///
+/// ```rust
+/// use pin_project::pin_project;
+/// use std::pin::Pin;
+///
+/// #[pin_project]
+/// struct Foo<T, U>(#[pin] T, U);
+///
+/// impl<T, U> Foo<T, U> {
+/// fn baz(self: Pin<&mut Self>) {
+/// let this = self.project();
+/// let _: Pin<&mut T> = this.0;
+/// let _: &mut U = this.1;
+/// }
+/// }
+/// ```
+///
+/// Structs without fields (unit-like struct and zero fields struct) are not
+/// supported.
+///
+/// ### Enums
+///
+/// `pin_project` also supports enums, but to use it, you need to use with the
+/// [`project`] attribute.
+///
+/// The attribute at the expression position is not stable, so you need to use
+/// a dummy `#[project]` attribute for the function.
+///
+/// ```rust
+/// use pin_project::{pin_project, project};
+/// use std::pin::Pin;
+///
+/// #[pin_project]
+/// enum Foo<A, B, C> {
+/// Tuple(#[pin] A, B),
+/// Struct { field: C },
+/// Unit,
+/// }
+///
+/// impl<A, B, C> Foo<A, B, C> {
+/// #[project] // Nightly does not need a dummy attribute to the function.
+/// fn baz(self: Pin<&mut Self>) {
+/// #[project]
+/// match self.project() {
+/// Foo::Tuple(x, y) => {
+/// let _: Pin<&mut A> = x;
+/// let _: &mut B = y;
+/// }
+/// Foo::Struct { field } => {
+/// let _: &mut C = field;
+/// }
+/// Foo::Unit => {}
+/// }
+/// }
+/// }
+/// ```
+///
+/// Enums without variants (zero-variant enums) are not supported.
+///
+/// See also [`project`] and [`project_ref`] attributes.
+///
+/// [`Pin::as_mut`]: core::pin::Pin::as_mut
+/// [`Pin::set`]: core::pin::Pin::set
+/// [`drop`]: Drop::drop
+/// [`UnsafeUnpin`]: https://docs.rs/pin-project/0.4/pin_project/trait.UnsafeUnpin.html
+/// [`project`]: ./attr.project.html
+/// [`project_ref`]: ./attr.project_ref.html
+/// [`pinned_drop`]: ./attr.pinned_drop.html
+#[proc_macro_attribute]
+pub fn pin_project(args: TokenStream, input: TokenStream) -> TokenStream {
+ pin_project::attribute(&args.into(), input.into()).into()
+}
+
+/// An attribute for annotating an impl block that implements [`Drop`].
+///
+/// This attribute is only needed when you wish to provide a [`Drop`]
+/// impl for your type. The impl block annotated with `#[pinned_drop]` acts just
+/// like a normal [`Drop`] impl, except for the fact that `drop` method takes
+/// `Pin<&mut Self>`. In particular, it will never be called more than once,
+/// just like [`Drop::drop`].
+///
+/// ## Example
+///
+/// ```rust
+/// use pin_project::{pin_project, pinned_drop};
+/// use std::pin::Pin;
+///
+/// #[pin_project(PinnedDrop)]
+/// struct Foo {
+/// #[pin]
+/// field: u8,
+/// }
+///
+/// #[pinned_drop]
+/// impl PinnedDrop for Foo {
+/// fn drop(self: Pin<&mut Self>) {
+/// println!("Dropping: {}", self.field);
+/// }
+/// }
+///
+/// fn main() {
+/// let _x = Foo { field: 50 };
+/// }
+/// ```
+///
+/// See ["pinned-drop" section of `pin_project` attribute][pinned-drop] for more details.
+///
+/// [pinned-drop]: ./attr.pin_project.html#pinned_drop
+#[proc_macro_attribute]
+pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
+ let input = syn::parse_macro_input!(input);
+ pinned_drop::attribute(&args.into(), input).into()
+}
+
+/// An attribute to provide way to refer to the projected type returned by
+/// `project` method.
+///
+/// The following syntaxes are supported.
+///
+/// ## `impl` blocks
+///
+/// All methods (and associated functions) in `#[project] impl` block become
+/// methods of the projected type. If you want to implement methods on the
+/// original type, you need to create another (non-`#[project]`) `impl` block.
+///
+/// To call a method implemented in `#[project] impl` block, you need to first
+/// get the projected-type with `let this = self.project();`.
+///
+/// ### Examples
+///
+/// ```rust
+/// use pin_project::{pin_project, project};
+/// use std::pin::Pin;
+///
+/// #[pin_project]
+/// struct Foo<T, U> {
+/// #[pin]
+/// future: T,
+/// field: U,
+/// }
+///
+/// // impl for the original type
+/// impl<T, U> Foo<T, U> {
+/// fn bar(self: Pin<&mut Self>) {
+/// self.project().baz()
+/// }
+/// }
+///
+/// // impl for the projected type
+/// #[project]
+/// impl<T, U> Foo<T, U> {
+/// fn baz(self) {
+/// let Self { future, field } = self;
+///
+/// let _: Pin<&mut T> = future;
+/// let _: &mut U = field;
+/// }
+/// }
+/// ```
+///
+/// ## `let` bindings
+///
+/// *The attribute at the expression position is not stable, so you need to use
+/// a dummy `#[project]` attribute for the function.*
+///
+/// ### Examples
+///
+/// ```rust
+/// use pin_project::{pin_project, project};
+/// use std::pin::Pin;
+///
+/// #[pin_project]
+/// struct Foo<T, U> {
+/// #[pin]
+/// future: T,
+/// field: U,
+/// }
+///
+/// impl<T, U> Foo<T, U> {
+/// #[project] // Nightly does not need a dummy attribute to the function.
+/// fn baz(self: Pin<&mut Self>) {
+/// #[project]
+/// let Foo { future, field } = self.project();
+///
+/// let _: Pin<&mut T> = future;
+/// let _: &mut U = field;
+/// }
+/// }
+/// ```
+///
+/// ## `match` expressions
+///
+/// *The attribute at the expression position is not stable, so you need to use
+/// a dummy `#[project]` attribute for the function.*
+///
+/// ### Examples
+///
+/// ```rust
+/// use pin_project::{pin_project, project};
+/// use std::pin::Pin;
+///
+/// #[pin_project]
+/// enum Foo<A, B, C> {
+/// Tuple(#[pin] A, B),
+/// Struct { field: C },
+/// Unit,
+/// }
+///
+/// impl<A, B, C> Foo<A, B, C> {
+/// #[project] // Nightly does not need a dummy attribute to the function.
+/// fn baz(self: Pin<&mut Self>) {
+/// #[project]
+/// match self.project() {
+/// Foo::Tuple(x, y) => {
+/// let _: Pin<&mut A> = x;
+/// let _: &mut B = y;
+/// }
+/// Foo::Struct { field } => {
+/// let _: &mut C = field;
+/// }
+/// Foo::Unit => {}
+/// }
+/// }
+/// }
+/// ```
+///
+/// ## `use` statements
+///
+/// ### Examples
+///
+/// ```rust
+/// # mod dox {
+/// use pin_project::pin_project;
+///
+/// #[pin_project]
+/// struct Foo<A> {
+/// #[pin]
+/// field: A,
+/// }
+///
+/// mod bar {
+/// use super::Foo;
+/// use pin_project::project;
+/// use std::pin::Pin;
+///
+/// #[project]
+/// use super::Foo;
+///
+/// #[project]
+/// fn baz<A>(foo: Pin<&mut Foo<A>>) {
+/// #[project]
+/// let Foo { field } = foo.project();
+/// let _: Pin<&mut A> = field;
+/// }
+/// }
+/// # }
+/// ```
+#[proc_macro_attribute]
+pub fn project(args: TokenStream, input: TokenStream) -> TokenStream {
+ let input = syn::parse_macro_input!(input);
+ project::attribute(&args.into(), input, Mutable).into()
+}
+
+/// An attribute to provide way to refer to the projected type returned by
+/// `project_ref` method.
+///
+/// This is the same as [`project`] attribute except it refers to the projected
+/// type returned by `project_ref` method.
+///
+/// See [`project`] attribute for more details.
+///
+/// [`project`]: ./attr.project.html
+#[proc_macro_attribute]
+pub fn project_ref(args: TokenStream, input: TokenStream) -> TokenStream {
+ let input = syn::parse_macro_input!(input);
+ project::attribute(&args.into(), input, Immutable).into()
+}
+
+/// An internal helper macro.
+#[doc(hidden)]
+#[proc_macro_derive(__PinProjectInternalDerive, attributes(pin))]
+pub fn __pin_project_internal_derive(input: TokenStream) -> TokenStream {
+ pin_project::derive(input.into()).into()
+}
diff --git a/third_party/rust/pin-project-internal/src/pin_project/attribute.rs b/third_party/rust/pin-project-internal/src/pin_project/attribute.rs
new file mode 100644
index 0000000000..7a0996e720
--- /dev/null
+++ b/third_party/rust/pin-project-internal/src/pin_project/attribute.rs
@@ -0,0 +1,71 @@
+use proc_macro2::{Span, TokenStream};
+use quote::quote;
+use syn::{
+ parse::{Parse, ParseStream},
+ *,
+};
+
+use crate::utils::{SliceExt, CURRENT_PRIVATE_MODULE};
+
+use super::PIN;
+
+// To generate the correct `Unpin` implementation and the projection methods,
+// we need to collect the types of the pinned fields.
+// However, since proc-macro-attribute is applied before `#[cfg]` and `#[cfg_attr]` on fields,
+// we cannot be collecting field types properly at this timing.
+// So instead of generating the `Unpin` implementation and the projection methods here,
+// delegate their processing to proc-macro-derive.
+//
+// At this stage, only attributes are parsed and the following attributes are
+// added to the attributes of the item.
+// * `#[derive(InternalDerive)]` - An internal helper macro that does the above processing.
+// * `#[pin(#private(#args))]` - Pass the argument of `#[pin_project]` to proc-macro-derive (`InternalDerive`).
+
+pub(super) fn parse_attribute(args: &TokenStream, input: TokenStream) -> Result<TokenStream> {
+ let Input { mut attrs, body } = syn::parse2(input)?;
+
+ let private = Ident::new(CURRENT_PRIVATE_MODULE, Span::call_site());
+ attrs.push(syn::parse_quote! {
+ #[derive(::pin_project::#private::__PinProjectInternalDerive)]
+ });
+ // Use `#private` to prevent users from trying to control `InternalDerive` manually.
+ // `#private` does not guarantee compatibility between patch versions,
+ // so it should be sufficient for this purpose in most cases.
+ attrs.push(syn::parse_quote! {
+ #[pin(#private(#args))]
+ });
+
+ Ok(quote! {
+ #(#attrs)*
+ #body
+ })
+}
+
+#[allow(dead_code)] // https://github.com/rust-lang/rust/issues/56750
+struct Input {
+ attrs: Vec<Attribute>,
+ body: TokenStream,
+}
+
+impl Parse for Input {
+ fn parse(input: ParseStream<'_>) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+
+ let ahead = input.fork();
+ let _vis: Visibility = ahead.parse()?;
+ if !ahead.peek(Token![struct]) && !ahead.peek(Token![enum]) {
+ // If we check this only on proc-macro-derive, it may generate unhelpful error messages.
+ // So it is preferable to be able to detect it here.
+ Err(error!(
+ input.parse::<TokenStream>()?,
+ "#[pin_project] attribute may only be used on structs or enums"
+ ))
+ } else if let Some(attr) = attrs.find(PIN) {
+ Err(error!(attr, "#[pin] attribute may only be used on fields of structs or variants"))
+ } else if let Some(attr) = attrs.find("pin_project") {
+ Err(error!(attr, "only one #[pin_project] attribute is allowed"))
+ } else {
+ Ok(Self { attrs, body: input.parse()? })
+ }
+ }
+}
diff --git a/third_party/rust/pin-project-internal/src/pin_project/derive.rs b/third_party/rust/pin-project-internal/src/pin_project/derive.rs
new file mode 100644
index 0000000000..30318f0483
--- /dev/null
+++ b/third_party/rust/pin-project-internal/src/pin_project/derive.rs
@@ -0,0 +1,834 @@
+use proc_macro2::{Span, TokenStream};
+use quote::{format_ident, quote, quote_spanned};
+use syn::{
+ parse::{Parse, ParseBuffer, ParseStream},
+ visit_mut::VisitMut,
+ *,
+};
+
+use crate::utils::*;
+
+use super::PIN;
+
+pub(super) fn parse_derive(input: TokenStream) -> Result<TokenStream> {
+ match syn::parse2(input)? {
+ Item::Struct(ItemStruct { attrs, vis, ident, generics, fields, .. }) => {
+ validate_struct(&ident, &fields)?;
+ let mut cx = Context::new(attrs, vis, ident, generics)?;
+
+ let packed_check = cx.ensure_not_packed(&fields)?;
+ let mut proj_items = cx.parse_struct(&fields)?;
+ proj_items.extend(packed_check);
+ proj_items.extend(cx.make_unpin_impl());
+ proj_items.extend(cx.make_drop_impl());
+ Ok(proj_items)
+ }
+ Item::Enum(ItemEnum { attrs, vis, ident, generics, brace_token, variants, .. }) => {
+ validate_enum(brace_token, &variants)?;
+ let mut cx = Context::new(attrs, vis, ident, generics)?;
+
+ // We don't need to check for '#[repr(packed)]',
+ // since it does not apply to enums.
+ let mut proj_items = cx.parse_enum(&variants)?;
+ proj_items.extend(cx.make_unpin_impl());
+ proj_items.extend(cx.make_drop_impl());
+ Ok(proj_items)
+ }
+ item => Err(error!(item, "#[pin_project] attribute may only be used on structs or enums")),
+ }
+}
+
+fn validate_struct(ident: &Ident, fields: &Fields) -> Result<()> {
+ match fields {
+ Fields::Named(FieldsNamed { named: f, .. })
+ | Fields::Unnamed(FieldsUnnamed { unnamed: f, .. })
+ if f.is_empty() =>
+ {
+ Err(error!(
+ fields,
+ "#[pin_project] attribute may not be used on structs with zero fields"
+ ))
+ }
+ Fields::Unit => {
+ Err(error!(ident, "#[pin_project] attribute may not be used on structs with units"))
+ }
+ _ => Ok(()),
+ }
+}
+
+fn validate_enum(brace_token: token::Brace, variants: &Variants) -> Result<()> {
+ if variants.is_empty() {
+ return Err(syn::Error::new(
+ brace_token.span,
+ "#[pin_project] attribute may not be used on enums without variants",
+ ));
+ }
+ let has_field = variants.iter().try_fold(false, |has_field, v| {
+ if let Some((_, e)) = &v.discriminant {
+ Err(error!(e, "#[pin_project] attribute may not be used on enums with discriminants"))
+ } else if let Some(attr) = v.attrs.find(PIN) {
+ Err(error!(attr, "#[pin] attribute may only be used on fields of structs or variants"))
+ } else if let Fields::Unit = v.fields {
+ Ok(has_field)
+ } else {
+ Ok(true)
+ }
+ })?;
+ if has_field {
+ Ok(())
+ } else {
+ Err(error!(
+ variants,
+ "#[pin_project] attribute may not be used on enums that have no field"
+ ))
+ }
+}
+
+#[derive(Default)]
+struct Args {
+ pinned_drop: Option<Span>,
+ unsafe_unpin: Option<Span>,
+}
+
+const DUPLICATE_PIN: &str = "duplicate #[pin] attribute";
+
+impl Args {
+ fn get(attrs: &[Attribute]) -> Result<Self> {
+ let mut prev: Option<(&Attribute, Result<Args>)> = None;
+
+ for attr in attrs {
+ if attr.path.is_ident(PIN) {
+ if let Some((prev_attr, prev_res)) = &prev {
+ // As the `#[pin]` attribute generated by `#[pin_project]`
+ // has the same span as `#[pin_project]`, it is possible
+ // that a useless error message will be generated.
+ let res = syn::parse2::<Self>(attr.tokens.clone());
+ let span = match (&prev_res, res) {
+ (Ok(_), Ok(_)) => unreachable!(),
+ (_, Ok(_)) => prev_attr,
+ (Ok(_), _) => attr,
+ (Err(prev_err), Err(_)) => {
+ if prev_err.to_string() == DUPLICATE_PIN {
+ attr
+ } else {
+ prev_attr
+ }
+ }
+ };
+ return Err(error!(span, DUPLICATE_PIN));
+ }
+ prev = Some((attr, syn::parse2::<Self>(attr.tokens.clone())));
+ }
+ }
+
+ // This `unwrap` only fails if another macro removes `#[pin]`.
+ prev.unwrap().1
+ }
+}
+
+impl Parse for Args {
+ fn parse(input: ParseStream<'_>) -> Result<Self> {
+ fn parse_input(input: ParseStream<'_>) -> Result<ParseBuffer<'_>> {
+ // Extracts `#args` from `(#private(#args))`.
+ if let Ok(content) = input.parenthesized() {
+ if let Ok(private) = content.parse::<Ident>() {
+ if private == CURRENT_PRIVATE_MODULE {
+ if let Ok(args) = content.parenthesized() {
+ return Ok(args);
+ }
+ }
+ }
+ }
+
+ // If this fails, it means that there is a `#[pin]` attribute
+ // inserted by something other than #[pin_project] attribute.
+ Err(error!(TokenStream::new(), DUPLICATE_PIN))
+ }
+
+ let input = parse_input(input)?;
+ let mut args = Self::default();
+ while !input.is_empty() {
+ let ident = input.parse::<Ident>()?;
+ match &*ident.to_string() {
+ "PinnedDrop" => {
+ if args.pinned_drop.is_some() {
+ return Err(error!(ident, "duplicate `PinnedDrop` argument"));
+ }
+ args.pinned_drop = Some(ident.span());
+ }
+ "UnsafeUnpin" => {
+ if args.unsafe_unpin.is_some() {
+ return Err(error!(ident, "duplicate `UnsafeUnpin` argument"));
+ }
+ args.unsafe_unpin = Some(ident.span());
+ }
+ _ => return Err(error!(ident, "unexpected argument: {}", ident)),
+ }
+
+ if !input.is_empty() {
+ let _: token::Comma = input.parse()?;
+ }
+ }
+
+ Ok(args)
+ }
+}
+
+struct OriginalType {
+ /// Attributes of the original type.
+ attrs: Vec<Attribute>,
+ /// Visibility of the original type.
+ vis: Visibility,
+ /// Name of the original type.
+ ident: Ident,
+ /// Generics of the original type.
+ generics: Generics,
+}
+
+struct ProjectedType {
+ /// Visibility of the projected type.
+ vis: Visibility,
+ /// Name of the projected type returned by `project` method.
+ mut_ident: Ident,
+ /// Name of the projected type returned by `project_ref` method.
+ ref_ident: Ident,
+ /// Lifetime on the generated projected type.
+ lifetime: Lifetime,
+ /// Generics of the projected type.
+ generics: Generics,
+ /// `where` clause of the projected type. This has an additional
+ /// bound generated by `insert_lifetime_and_bound`
+ where_clause: WhereClause,
+}
+
+struct Context {
+ orig: OriginalType,
+ proj: ProjectedType,
+ /// Types of the pinned fields.
+ pinned_fields: Vec<Type>,
+ /// `PinnedDrop` attribute.
+ pinned_drop: Option<Span>,
+ /// `UnsafeUnpin` attribute.
+ unsafe_unpin: Option<Span>,
+}
+
+impl Context {
+ fn new(
+ attrs: Vec<Attribute>,
+ vis: Visibility,
+ ident: Ident,
+ mut generics: Generics,
+ ) -> Result<Self> {
+ let Args { pinned_drop, unsafe_unpin } = Args::get(&attrs)?;
+
+ {
+ let ty_generics = generics.split_for_impl().1;
+ let self_ty = syn::parse_quote!(#ident #ty_generics);
+ let mut visitor = ReplaceReceiver::new(&self_ty);
+ visitor.visit_where_clause_mut(generics.make_where_clause());
+ }
+
+ let mut lifetime_name = String::from(DEFAULT_LIFETIME_NAME);
+ determine_lifetime_name(&mut lifetime_name, &generics.params);
+ let lifetime = Lifetime::new(&lifetime_name, Span::call_site());
+
+ let mut proj_generics = generics.clone();
+ let ty_generics = generics.split_for_impl().1;
+ let ty_generics_as_generics = syn::parse_quote!(#ty_generics);
+ let pred = insert_lifetime_and_bound(
+ &mut proj_generics,
+ lifetime.clone(),
+ &ty_generics_as_generics,
+ ident.clone(),
+ );
+ let mut where_clause = generics.clone().make_where_clause().clone();
+ where_clause.predicates.push(pred);
+
+ Ok(Self {
+ proj: ProjectedType {
+ vis: determine_visibility(&vis),
+ mut_ident: proj_ident(&ident, Mutable),
+ ref_ident: proj_ident(&ident, Immutable),
+ lifetime,
+ generics: proj_generics,
+ where_clause,
+ },
+ orig: OriginalType { attrs, vis, ident, generics },
+ pinned_drop,
+ unsafe_unpin,
+ pinned_fields: Vec::new(),
+ })
+ }
+
+ fn parse_struct(&mut self, fields: &Fields) -> Result<TokenStream> {
+ let (proj_pat, proj_init, proj_fields, proj_ref_fields) = match fields {
+ Fields::Named(fields) => self.visit_named(fields)?,
+ Fields::Unnamed(fields) => self.visit_unnamed(fields)?,
+ Fields::Unit => unreachable!(),
+ };
+
+ let orig_ident = &self.orig.ident;
+ let proj_ident = &self.proj.mut_ident;
+ let proj_ref_ident = &self.proj.ref_ident;
+ let vis = &self.proj.vis;
+ let proj_generics = &self.proj.generics;
+ let where_clause = &self.proj.where_clause;
+
+ // For tuple structs, we need to generate `(T1, T2) where Foo: Bar`
+ // For non-tuple structs, we need to generate `where Foo: Bar { field1: T }`
+ let (where_clause_fields, where_clause_ref_fields) = match fields {
+ Fields::Named(_) => {
+ (quote!(#where_clause #proj_fields), quote!(#where_clause #proj_ref_fields))
+ }
+ Fields::Unnamed(_) => {
+ (quote!(#proj_fields #where_clause;), quote!(#proj_ref_fields #where_clause;))
+ }
+ Fields::Unit => unreachable!(),
+ };
+
+ let mut proj_items = quote! {
+ #[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
+ #[allow(dead_code)] // This lint warns unused fields/variants.
+ #vis struct #proj_ident #proj_generics #where_clause_fields
+ #[allow(dead_code)] // This lint warns unused fields/variants.
+ #vis struct #proj_ref_ident #proj_generics #where_clause_ref_fields
+ };
+
+ let proj_body = quote! {
+ let #orig_ident #proj_pat = self.get_unchecked_mut();
+ #proj_ident #proj_init
+ };
+ let proj_ref_body = quote! {
+ let #orig_ident #proj_pat = self.get_ref();
+ #proj_ref_ident #proj_init
+ };
+
+ proj_items.extend(self.make_proj_impl(&proj_body, &proj_ref_body));
+
+ Ok(proj_items)
+ }
+
+ fn parse_enum(&mut self, variants: &Variants) -> Result<TokenStream> {
+ let (proj_variants, proj_ref_variants, proj_arms, proj_ref_arms) =
+ self.visit_variants(variants)?;
+
+ let proj_ident = &self.proj.mut_ident;
+ let proj_ref_ident = &self.proj.ref_ident;
+ let vis = &self.proj.vis;
+ let proj_generics = &self.proj.generics;
+ let where_clause = &self.proj.where_clause;
+
+ let mut proj_items = quote! {
+ #[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
+ #[allow(dead_code)] // This lint warns unused fields/variants.
+ #vis enum #proj_ident #proj_generics #where_clause {
+ #proj_variants
+ }
+ #[allow(dead_code)] // This lint warns unused fields/variants.
+ #vis enum #proj_ref_ident #proj_generics #where_clause {
+ #proj_ref_variants
+ }
+ };
+
+ let proj_body = quote! {
+ match self.get_unchecked_mut() {
+ #proj_arms
+ }
+ };
+ let proj_ref_body = quote! {
+ match self.get_ref() {
+ #proj_ref_arms
+ }
+ };
+
+ proj_items.extend(self.make_proj_impl(&proj_body, &proj_ref_body));
+
+ Ok(proj_items)
+ }
+
+ fn visit_variants(
+ &mut self,
+ variants: &Variants,
+ ) -> Result<(TokenStream, TokenStream, TokenStream, TokenStream)> {
+ let mut proj_variants = TokenStream::new();
+ let mut proj_ref_variants = TokenStream::new();
+ let mut proj_arms = TokenStream::new();
+ let mut proj_ref_arms = TokenStream::new();
+ for Variant { ident, fields, .. } in variants {
+ let (proj_pat, proj_body, proj_fields, proj_ref_fields) = match fields {
+ Fields::Named(fields) => self.visit_named(fields)?,
+ Fields::Unnamed(fields) => self.visit_unnamed(fields)?,
+ Fields::Unit => {
+ (TokenStream::new(), TokenStream::new(), TokenStream::new(), TokenStream::new())
+ }
+ };
+
+ let orig_ident = &self.orig.ident;
+ let proj_ident = &self.proj.mut_ident;
+ let proj_ref_ident = &self.proj.ref_ident;
+ proj_variants.extend(quote! {
+ #ident #proj_fields,
+ });
+ proj_ref_variants.extend(quote! {
+ #ident #proj_ref_fields,
+ });
+ proj_arms.extend(quote! {
+ #orig_ident::#ident #proj_pat => {
+ #proj_ident::#ident #proj_body
+ }
+ });
+ proj_ref_arms.extend(quote! {
+ #orig_ident::#ident #proj_pat => {
+ #proj_ref_ident::#ident #proj_body
+ }
+ });
+ }
+
+ Ok((proj_variants, proj_ref_variants, proj_arms, proj_ref_arms))
+ }
+
+ fn visit_named(
+ &mut self,
+ FieldsNamed { named: fields, .. }: &FieldsNamed,
+ ) -> Result<(TokenStream, TokenStream, TokenStream, TokenStream)> {
+ let mut proj_pat = Vec::with_capacity(fields.len());
+ let mut proj_body = Vec::with_capacity(fields.len());
+ let mut proj_fields = Vec::with_capacity(fields.len());
+ let mut proj_ref_fields = Vec::with_capacity(fields.len());
+ for Field { attrs, vis, ident, ty, .. } in fields {
+ if attrs.find_exact(PIN)?.is_some() {
+ self.pinned_fields.push(ty.clone());
+
+ let lifetime = &self.proj.lifetime;
+ proj_fields.push(quote! {
+ #vis #ident: ::core::pin::Pin<&#lifetime mut (#ty)>
+ });
+ proj_ref_fields.push(quote! {
+ #vis #ident: ::core::pin::Pin<&#lifetime (#ty)>
+ });
+ proj_body.push(quote! {
+ #ident: ::core::pin::Pin::new_unchecked(#ident)
+ });
+ } else {
+ let lifetime = &self.proj.lifetime;
+ proj_fields.push(quote! {
+ #vis #ident: &#lifetime mut (#ty)
+ });
+ proj_ref_fields.push(quote! {
+ #vis #ident: &#lifetime (#ty)
+ });
+ proj_body.push(quote! {
+ #ident
+ });
+ }
+ proj_pat.push(ident);
+ }
+
+ let proj_pat = quote!({ #(#proj_pat),* });
+ let proj_body = quote!({ #(#proj_body),* });
+ let proj_fields = quote!({ #(#proj_fields),* });
+ let proj_ref_fields = quote!({ #(#proj_ref_fields),* });
+
+ Ok((proj_pat, proj_body, proj_fields, proj_ref_fields))
+ }
+
+ fn visit_unnamed(
+ &mut self,
+ FieldsUnnamed { unnamed: fields, .. }: &FieldsUnnamed,
+ ) -> Result<(TokenStream, TokenStream, TokenStream, TokenStream)> {
+ let mut proj_pat = Vec::with_capacity(fields.len());
+ let mut proj_body = Vec::with_capacity(fields.len());
+ let mut proj_fields = Vec::with_capacity(fields.len());
+ let mut proj_ref_fields = Vec::with_capacity(fields.len());
+ for (i, Field { attrs, vis, ty, .. }) in fields.iter().enumerate() {
+ let id = format_ident!("_{}", i);
+ if attrs.find_exact(PIN)?.is_some() {
+ self.pinned_fields.push(ty.clone());
+
+ let lifetime = &self.proj.lifetime;
+ proj_fields.push(quote! {
+ #vis ::core::pin::Pin<&#lifetime mut (#ty)>
+ });
+ proj_ref_fields.push(quote! {
+ #vis ::core::pin::Pin<&#lifetime (#ty)>
+ });
+ proj_body.push(quote! {
+ ::core::pin::Pin::new_unchecked(#id)
+ });
+ } else {
+ let lifetime = &self.proj.lifetime;
+ proj_fields.push(quote! {
+ #vis &#lifetime mut (#ty)
+ });
+ proj_ref_fields.push(quote! {
+ #vis &#lifetime (#ty)
+ });
+ proj_body.push(quote! {
+ #id
+ });
+ }
+ proj_pat.push(id);
+ }
+
+ let proj_pat = quote!((#(#proj_pat),*));
+ let proj_body = quote!((#(#proj_body),*));
+ let (proj_fields, proj_ref_fields) =
+ (quote!((#(#proj_fields),*)), quote!((#(#proj_ref_fields),*)));
+
+ Ok((proj_pat, proj_body, proj_fields, proj_ref_fields))
+ }
+
+ /// Creates conditional `Unpin` implementation for original type.
+ fn make_unpin_impl(&mut self) -> TokenStream {
+ if let Some(unsafe_unpin) = self.unsafe_unpin {
+ let mut proj_generics = self.proj.generics.clone();
+ let orig_ident = &self.orig.ident;
+ let lifetime = &self.proj.lifetime;
+
+ let private = Ident::new(CURRENT_PRIVATE_MODULE, Span::call_site());
+ proj_generics.make_where_clause().predicates.push(
+ // Make the error message highlight `UnsafeUnpin` argument.
+ syn::parse2(quote_spanned! { unsafe_unpin =>
+ ::pin_project::#private::Wrapper<#lifetime, Self>: ::pin_project::UnsafeUnpin
+ })
+ .unwrap(),
+ );
+
+ let (impl_generics, _, where_clause) = proj_generics.split_for_impl();
+ let ty_generics = self.orig.generics.split_for_impl().1;
+
+ quote! {
+ #[allow(single_use_lifetimes)]
+ impl #impl_generics ::core::marker::Unpin for #orig_ident #ty_generics #where_clause {}
+ }
+ } else {
+ let mut full_where_clause = self.orig.generics.where_clause.as_ref().cloned().unwrap();
+ let orig_ident = &self.orig.ident;
+
+ let make_span = || {
+ #[cfg(pin_project_show_unpin_struct)]
+ {
+ proc_macro::Span::def_site().into()
+ }
+ #[cfg(not(pin_project_show_unpin_struct))]
+ {
+ Span::call_site()
+ }
+ };
+
+ let struct_ident = format_ident!("__{}", orig_ident, span = make_span());
+
+ // Generate a field in our new struct for every
+ // pinned field in the original type.
+ let fields: Vec<_> = self
+ .pinned_fields
+ .iter()
+ .enumerate()
+ .map(|(i, ty)| {
+ let field_ident = format_ident!("__field{}", i);
+ quote! {
+ #field_ident: #ty
+ }
+ })
+ .collect();
+
+ // We could try to determine the subset of type parameters
+ // and lifetimes that are actually used by the pinned fields
+ // (as opposed to those only used by unpinned fields).
+ // However, this would be tricky and error-prone, since
+ // it's possible for users to create types that would alias
+ // with generic parameters (e.g. 'struct T').
+ //
+ // Instead, we generate a use of every single type parameter
+ // and lifetime used in the original struct. For type parameters,
+ // we generate code like this:
+ //
+ // ```rust
+ // struct AlwaysUnpin<T: ?Sized>(PhantomData<T>) {}
+ // impl<T: ?Sized> Unpin for AlwaysUnpin<T> {}
+ //
+ // ...
+ // _field: AlwaysUnpin<(A, B, C)>
+ // ```
+ //
+ // This ensures that any unused type parameters
+ // don't end up with Unpin bounds.
+ let lifetime_fields: Vec<_> = self
+ .orig
+ .generics
+ .lifetimes()
+ .enumerate()
+ .map(|(i, LifetimeDef { lifetime, .. })| {
+ let field_ident = format_ident!("__lifetime{}", i);
+ quote! {
+ #field_ident: &#lifetime ()
+ }
+ })
+ .collect();
+
+ let scope_ident = format_ident!("__unpin_scope_{}", orig_ident);
+
+ let vis = &self.orig.vis;
+ let lifetime = &self.proj.lifetime;
+ let type_params: Vec<_> = self.orig.generics.type_params().map(|t| &t.ident).collect();
+ let proj_generics = &self.proj.generics;
+ let (impl_generics, proj_ty_generics, _) = proj_generics.split_for_impl();
+ let (_, ty_generics, where_clause) = self.orig.generics.split_for_impl();
+
+ full_where_clause.predicates.push(syn::parse_quote! {
+ #struct_ident #proj_ty_generics: ::core::marker::Unpin
+ });
+
+ let private = Ident::new(CURRENT_PRIVATE_MODULE, Span::call_site());
+ let inner_data = quote! {
+ // This needs to have the same visibility as the original type,
+ // due to the limitations of the 'public in private' error.
+ //
+ // Out goal is to implement the public trait Unpin for
+ // a potentially public user type. Because of this, rust
+ // requires that any types mentioned in the where clause of
+ // our Unpin impl also be public. This means that our generated
+ // 'UnpinStruct' type must also be public. However, we take
+ // steps to ensure that the user can never actually reference
+ // this 'public' type. These steps are described below.
+ //
+ // See also https://github.com/taiki-e/pin-project/pull/53.
+ #vis struct #struct_ident #proj_generics #where_clause {
+ __pin_project_use_generics: ::pin_project::#private::AlwaysUnpin<#lifetime, (#(#type_params),*)>,
+
+ #(#fields,)*
+ #(#lifetime_fields,)*
+ }
+
+ impl #impl_generics ::core::marker::Unpin for #orig_ident #ty_generics #full_where_clause {}
+ };
+
+ if cfg!(pin_project_show_unpin_struct) {
+ // On nightly, we use def-site hygiene to make it impossible
+ // for user code to refer to any of the types we define.
+ // This allows us to omit wrapping the generated types
+ // in an fn() scope, allowing rustdoc to properly document
+ // them.
+ inner_data
+ } else {
+ // When we're not on nightly, we need to create an enclosing fn() scope
+ // for all of our generated items. This makes it impossible for
+ // user code to refer to any of our generated types, but has
+ // the advantage of preventing Rustdoc from displaying
+ // docs for any of our types. In particular, users cannot see
+ // the automatically generated Unpin impl for the 'UnpinStruct$Name' types.
+ quote! {
+ #[allow(non_snake_case)]
+ fn #scope_ident() {
+ #inner_data
+ }
+ }
+ }
+ }
+ }
+
+ /// Creates `Drop` implementation for original type.
+ fn make_drop_impl(&self) -> TokenStream {
+ let ident = &self.orig.ident;
+ let (impl_generics, ty_generics, where_clause) = self.orig.generics.split_for_impl();
+
+ let private = Ident::new(CURRENT_PRIVATE_MODULE, Span::call_site());
+ if let Some(pinned_drop) = self.pinned_drop {
+ // Make the error message highlight `PinnedDrop` argument.
+ // See https://github.com/taiki-e/pin-project/issues/16#issuecomment-513586812
+ // for why this is only for the span of function calls, not the entire `impl` block.
+ let call_drop = quote_spanned! { pinned_drop =>
+ ::pin_project::#private::PinnedDrop::drop(pinned_self)
+ };
+
+ quote! {
+ #[allow(single_use_lifetimes)]
+ impl #impl_generics ::core::ops::Drop for #ident #ty_generics #where_clause {
+ fn drop(&mut self) {
+ // Safety - we're in 'drop', so we know that 'self' will
+ // never move again.
+ let pinned_self = unsafe { ::core::pin::Pin::new_unchecked(self) };
+ // We call `pinned_drop` only once. Since `PinnedDrop::drop`
+ // is an unsafe function and a private API, it is never called again in safe
+ // code *unless the user uses a maliciously crafted macro*.
+ unsafe {
+ #call_drop;
+ }
+ }
+ }
+ }
+ } else {
+ // If the user does not provide a pinned_drop impl,
+ // we need to ensure that they don't provide a `Drop` impl of their
+ // own.
+ // Based on https://github.com/upsuper/assert-impl/blob/f503255b292ab0ba8d085b657f4065403cfa46eb/src/lib.rs#L80-L87
+ //
+ // We create a new identifier for each struct, so that the traits
+ // for different types do not conflict with each other.
+ //
+ // Another approach would be to provide an empty Drop impl,
+ // which would conflict with a user-provided Drop impl.
+ // However, this would trigger the compiler's special handling
+ // of Drop types (e.g. fields cannot be moved out of a Drop type).
+ // This approach prevents the creation of needless Drop impls,
+ // giving users more flexibility.
+ let trait_ident = format_ident!("{}MustNotImplDrop", ident);
+
+ quote! {
+ // 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 conflict with the explicit MustNotImplDrop impl below.
+ // This will result in a compilation error, which is exactly what we want.
+ trait #trait_ident {}
+ #[allow(clippy::drop_bounds)]
+ impl<T: ::core::ops::Drop> #trait_ident for T {}
+ #[allow(single_use_lifetimes)]
+ impl #impl_generics #trait_ident for #ident #ty_generics #where_clause {}
+
+ // A dummy impl of `PinnedDrop`, to ensure that the user cannot implement it.
+ // Since the user did not pass `PinnedDrop` to `#[pin_project]`, any `PinnedDrop`
+ // impl will not actually be called. Unfortunately, we can't detect this situation
+ // directly from either the `#[pin_project]` or `#[pinned_drop]` attributes, since
+ // we don't know what other attirbutes/impl may exist.
+ //
+ // To ensure that users don't accidentally write a non-functional `PinnedDrop`
+ // impls, we emit one ourselves. If the user ends up writing a `PinnedDrop` impl,
+ // they'll get a "conflicting implementations of trait" error when coherence
+ // checks are run
+ #[allow(single_use_lifetimes)]
+ impl #impl_generics ::pin_project::#private::PinnedDrop for #ident #ty_generics #where_clause {
+ unsafe fn drop(self: ::core::pin::Pin<&mut Self>) {}
+ }
+ }
+ }
+ }
+
+ /// Creates an implementation of the projection method.
+ fn make_proj_impl(&self, proj_body: &TokenStream, proj_ref_body: &TokenStream) -> TokenStream {
+ let vis = &self.proj.vis;
+ let lifetime = &self.proj.lifetime;
+ let orig_ident = &self.orig.ident;
+ let proj_ident = &self.proj.mut_ident;
+ let proj_ref_ident = &self.proj.ref_ident;
+
+ let proj_ty_generics = self.proj.generics.split_for_impl().1;
+ let (impl_generics, ty_generics, where_clause) = self.orig.generics.split_for_impl();
+
+ quote! {
+ impl #impl_generics #orig_ident #ty_generics #where_clause {
+ #vis fn project<#lifetime>(
+ self: ::core::pin::Pin<&#lifetime mut Self>,
+ ) -> #proj_ident #proj_ty_generics {
+ unsafe {
+ #proj_body
+ }
+ }
+ #vis fn project_ref<#lifetime>(
+ self: ::core::pin::Pin<&#lifetime Self>,
+ ) -> #proj_ref_ident #proj_ty_generics {
+ unsafe {
+ #proj_ref_body
+ }
+ }
+ }
+ }
+ }
+
+ fn ensure_not_packed(&self, fields: &Fields) -> Result<TokenStream> {
+ for meta in self.orig.attrs.iter().filter_map(|attr| attr.parse_meta().ok()) {
+ if let Meta::List(l) = meta {
+ if l.path.is_ident("repr") {
+ for repr in l.nested.iter() {
+ match repr {
+ NestedMeta::Meta(Meta::Path(path))
+ | NestedMeta::Meta(Meta::List(MetaList { path, .. }))
+ if path.is_ident("packed") =>
+ {
+ return Err(error!(
+ repr,
+ "#[pin_project] attribute may not be used on #[repr(packed)] types"
+ ));
+ }
+ _ => {}
+ }
+ }
+ }
+ }
+ }
+
+ // As proc-macro-derive can't rewrite the structure definition,
+ // it's probably no longer necessary, but it keeps it for now.
+
+ // Workaround for https://github.com/taiki-e/pin-project/issues/32
+ // Through the tricky use of proc macros, it's possible to bypass
+ // the above check for the 'repr' attribute.
+ // To ensure that it's impossible to use pin projections on a #[repr(packed)]
+ // struct, we generate code like this:
+ //
+ // #[deny(safe_packed_borrows)]
+ // fn enforce_not_packed_for_MyStruct(val: &MyStruct) {
+ // let _field1 = &val.field1;
+ // let _field2 = &val.field2;
+ // ...
+ // let _fieldn = &val.fieldn;
+ // }
+ //
+ // Taking a reference to a packed field is unsafe, and applying
+ // #[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.
+ //
+ // There is one exception: If the type of a struct field has an alignment of 1
+ // (e.g. u8), it is always safe to take a reference to it, even if the struct
+ // is #[repr(packed)]. If the struct is composed entirely of types of alignment 1,
+ // our generated method will not trigger an error if the struct is #[repr(packed)]
+ //
+ // Fortunately, this should have no observable consequence - #[repr(packed)]
+ // is essentially a no-op on such a type. Nevertheless, we include a test
+ // to ensure that the compiler doesn't ever try to copy the fields on
+ // such a struct when trying to drop it - which is reason we prevent
+ // #[repr(packed)] in the first place.
+ //
+ // See also https://github.com/taiki-e/pin-project/pull/34.
+ let mut field_refs = vec![];
+ match fields {
+ Fields::Named(FieldsNamed { named, .. }) => {
+ for Field { ident, .. } in named {
+ field_refs.push(quote! {
+ &val.#ident;
+ });
+ }
+ }
+ Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => {
+ for (index, _) in unnamed.iter().enumerate() {
+ let index = Index::from(index);
+ field_refs.push(quote! {
+ &val.#index;
+ });
+ }
+ }
+ Fields::Unit => {}
+ }
+
+ let (impl_generics, ty_generics, where_clause) = self.orig.generics.split_for_impl();
+
+ let struct_name = &self.orig.ident;
+ let method_name = format_ident!("__pin_project_assert_not_repr_packed_{}", self.orig.ident);
+ Ok(quote! {
+ #[allow(single_use_lifetimes)]
+ #[allow(non_snake_case)]
+ #[deny(safe_packed_borrows)]
+ fn #method_name #impl_generics (val: &#struct_name #ty_generics) #where_clause {
+ #(#field_refs)*
+ }
+ })
+ }
+}
diff --git a/third_party/rust/pin-project-internal/src/pin_project/mod.rs b/third_party/rust/pin-project-internal/src/pin_project/mod.rs
new file mode 100644
index 0000000000..e8d83aacf7
--- /dev/null
+++ b/third_party/rust/pin-project-internal/src/pin_project/mod.rs
@@ -0,0 +1,15 @@
+use proc_macro2::TokenStream;
+
+mod attribute;
+mod derive;
+
+/// The annotation for pinned type.
+const PIN: &str = "pin";
+
+pub(crate) fn attribute(args: &TokenStream, input: TokenStream) -> TokenStream {
+ attribute::parse_attribute(args, input).unwrap_or_else(|e| e.to_compile_error())
+}
+
+pub(crate) fn derive(input: TokenStream) -> TokenStream {
+ derive::parse_derive(input).unwrap_or_else(|e| e.to_compile_error())
+}
diff --git a/third_party/rust/pin-project-internal/src/pinned_drop.rs b/third_party/rust/pin-project-internal/src/pinned_drop.rs
new file mode 100644
index 0000000000..11cc37dc50
--- /dev/null
+++ b/third_party/rust/pin-project-internal/src/pinned_drop.rs
@@ -0,0 +1,199 @@
+use proc_macro2::{Span, TokenStream};
+use quote::{quote, quote_spanned, ToTokens};
+use syn::{spanned::Spanned, visit_mut::VisitMut, *};
+
+use crate::utils::{
+ parse_as_empty, prepend_underscore_to_self, ReplaceReceiver, CURRENT_PRIVATE_MODULE,
+};
+
+pub(crate) fn attribute(args: &TokenStream, mut input: ItemImpl) -> TokenStream {
+ if let Err(e) = parse_as_empty(args).and_then(|()| parse(&mut input)) {
+ let self_ty = &input.self_ty;
+ let (impl_generics, _, where_clause) = input.generics.split_for_impl();
+
+ let mut tokens = e.to_compile_error();
+ let private = Ident::new(CURRENT_PRIVATE_MODULE, Span::call_site());
+ // Generate a dummy `PinnedDrop` implementation.
+ // In many cases, `#[pinned_drop] impl` is declared after `#[pin_project]`.
+ // Therefore, if `pinned_drop` compile fails, you will also get an error
+ // about `PinnedDrop` not being implemented.
+ // This can be prevented to some extent by generating a dummy
+ // `PinnedDrop` implementation.
+ // We already know that we will get a compile error, so this won't
+ // accidentally compile successfully.
+ tokens.extend(quote! {
+ impl #impl_generics ::pin_project::#private::PinnedDrop for #self_ty #where_clause {
+ unsafe fn drop(self: ::core::pin::Pin<&mut Self>) {}
+ }
+ });
+ tokens
+ } else {
+ input.into_token_stream()
+ }
+}
+
+fn parse_method(method: &ImplItemMethod) -> Result<()> {
+ fn get_ty_path(ty: &Type) -> Option<&Path> {
+ if let Type::Path(TypePath { qself: None, path }) = ty { Some(path) } else { None }
+ }
+
+ const INVALID_ARGUMENT: &str = "method `drop` must take an argument `self: Pin<&mut Self>`";
+
+ if method.sig.ident != "drop" {
+ return Err(error!(
+ method.sig.ident,
+ "method `{}` is not a member of trait `PinnedDrop", method.sig.ident,
+ ));
+ }
+
+ if let ReturnType::Type(_, ty) = &method.sig.output {
+ match &**ty {
+ Type::Tuple(TypeTuple { elems, .. }) if elems.is_empty() => {}
+ _ => return Err(error!(ty, "method `drop` must return the unit type")),
+ }
+ }
+
+ if method.sig.inputs.len() != 1 {
+ if method.sig.inputs.is_empty() {
+ return Err(syn::Error::new(method.sig.paren_token.span, INVALID_ARGUMENT));
+ } else {
+ return Err(error!(&method.sig.inputs, INVALID_ARGUMENT));
+ }
+ }
+
+ if let FnArg::Typed(PatType { pat, ty, .. }) = &method.sig.inputs[0] {
+ // !by_ref (mutability) ident !subpat: path
+ if let (Pat::Ident(PatIdent { by_ref: None, ident, subpat: None, .. }), Some(path)) =
+ (&**pat, get_ty_path(ty))
+ {
+ let ty = &path.segments.last().unwrap();
+ if let PathArguments::AngleBracketed(args) = &ty.arguments {
+ // (mut) self: (path::)Pin<args>
+ if ident == "self" && args.args.len() == 1 && ty.ident == "Pin" {
+ // &mut <elem>
+ if let GenericArgument::Type(Type::Reference(TypeReference {
+ mutability: Some(_),
+ elem,
+ ..
+ })) = &args.args[0]
+ {
+ if get_ty_path(elem).map_or(false, |path| path.is_ident("Self")) {
+ if method.sig.unsafety.is_some() {
+ return Err(error!(
+ method.sig.unsafety,
+ "implementing the method `drop` is not unsafe"
+ ));
+ }
+ return Ok(());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Err(error!(method.sig.inputs[0], INVALID_ARGUMENT))
+}
+
+fn parse(item: &mut ItemImpl) -> Result<()> {
+ if let Some((_, path, _)) = &mut item.trait_ {
+ if path.is_ident("PinnedDrop") {
+ let private = Ident::new(CURRENT_PRIVATE_MODULE, Span::call_site());
+ *path = syn::parse2(quote_spanned! { path.span() =>
+ ::pin_project::#private::PinnedDrop
+ })
+ .unwrap();
+ } else {
+ return Err(error!(
+ path,
+ "#[pinned_drop] may only be used on implementation for the `PinnedDrop` trait"
+ ));
+ }
+ } else {
+ return Err(error!(
+ item.self_ty,
+ "#[pinned_drop] may only be used on implementation for the `PinnedDrop` trait"
+ ));
+ }
+
+ if item.unsafety.is_some() {
+ return Err(error!(item.unsafety, "implementing the trait `PinnedDrop` is not unsafe"));
+ }
+ if item.items.is_empty() {
+ return Err(error!(item, "not all trait items implemented, missing: `drop`"));
+ }
+
+ for (i, item) in item.items.iter().enumerate() {
+ match item {
+ ImplItem::Const(item) => {
+ return Err(error!(
+ item,
+ "const `{}` is not a member of trait `PinnedDrop`", item.ident
+ ));
+ }
+ ImplItem::Type(item) => {
+ return Err(error!(
+ item,
+ "type `{}` is not a member of trait `PinnedDrop`", item.ident
+ ));
+ }
+ ImplItem::Method(method) => {
+ parse_method(method)?;
+ if i != 0 {
+ return Err(error!(method, "duplicate definitions with name `drop`"));
+ }
+ }
+ _ => parse_as_empty(&item.to_token_stream())?,
+ }
+ }
+
+ expand_item(item);
+
+ Ok(())
+}
+
+// from:
+//
+// fn drop(self: Pin<&mut Self>) {
+// // something
+// }
+//
+// into:
+//
+// unsafe fn drop(self: Pin<&mut Self>) {
+// fn __drop_inner<T>(__self: Pin<&mut Foo<'_, T>>) {
+// // something
+// }
+// __drop_inner(self);
+// }
+//
+fn expand_item(item: &mut ItemImpl) {
+ let method =
+ if let ImplItem::Method(method) = &mut item.items[0] { method } else { unreachable!() };
+ let mut drop_inner = method.clone();
+
+ // `fn drop(mut self: Pin<&mut Self>)` -> `fn __drop_inner<T>(mut __self: Pin<&mut Receiver>)`
+ drop_inner.sig.ident = Ident::new("__drop_inner", drop_inner.sig.ident.span());
+ drop_inner.sig.generics = item.generics.clone();
+ if let FnArg::Typed(arg) = &mut drop_inner.sig.inputs[0] {
+ if let Pat::Ident(ident) = &mut *arg.pat {
+ prepend_underscore_to_self(&mut ident.ident);
+ }
+ }
+ let mut visitor = ReplaceReceiver::new(&item.self_ty);
+ visitor.visit_signature_mut(&mut drop_inner.sig);
+ visitor.visit_block_mut(&mut drop_inner.block);
+
+ // `fn drop(mut self: Pin<&mut Self>)` -> `unsafe fn drop(self: Pin<&mut Self>)`
+ method.sig.unsafety = Some(token::Unsafe::default());
+ if let FnArg::Typed(arg) = &mut method.sig.inputs[0] {
+ if let Pat::Ident(ident) = &mut *arg.pat {
+ ident.mutability = None;
+ }
+ }
+
+ method.block = syn::parse_quote! {{
+ #drop_inner
+ __drop_inner(self);
+ }};
+}
diff --git a/third_party/rust/pin-project-internal/src/project.rs b/third_party/rust/pin-project-internal/src/project.rs
new file mode 100644
index 0000000000..92627d435b
--- /dev/null
+++ b/third_party/rust/pin-project-internal/src/project.rs
@@ -0,0 +1,286 @@
+use proc_macro2::{Span, TokenStream};
+use quote::ToTokens;
+use syn::{
+ visit_mut::{self, VisitMut},
+ *,
+};
+
+use crate::utils::*;
+
+pub(crate) fn attribute(args: &TokenStream, input: Stmt, mutability: Mutability) -> TokenStream {
+ parse_as_empty(args)
+ .and_then(|()| parse(input, mutability))
+ .unwrap_or_else(|e| e.to_compile_error())
+}
+
+fn replace_stmt(stmt: &mut Stmt, mutability: Mutability) -> Result<()> {
+ match stmt {
+ Stmt::Expr(Expr::Match(expr)) | Stmt::Semi(Expr::Match(expr), _) => {
+ Context::new(mutability).replace_expr_match(expr);
+ }
+ Stmt::Expr(Expr::If(expr_if)) => {
+ let mut expr_if = expr_if;
+ while let Expr::Let(ref mut expr) = &mut *expr_if.cond {
+ Context::new(mutability).replace_expr_let(expr);
+ if let Some((_, ref mut expr)) = expr_if.else_branch {
+ if let Expr::If(new_expr_if) = &mut **expr {
+ expr_if = new_expr_if;
+ continue;
+ }
+ }
+ break;
+ }
+ }
+ Stmt::Local(local) => Context::new(mutability).replace_local(local)?,
+ _ => {}
+ }
+ Ok(())
+}
+
+fn parse(mut stmt: Stmt, mutability: Mutability) -> Result<TokenStream> {
+ replace_stmt(&mut stmt, mutability)?;
+ match &mut stmt {
+ Stmt::Item(Item::Fn(item)) => replace_item_fn(item, mutability)?,
+ Stmt::Item(Item::Impl(item)) => replace_item_impl(item, mutability),
+ Stmt::Item(Item::Use(item)) => replace_item_use(item, mutability)?,
+ _ => {}
+ }
+
+ Ok(stmt.into_token_stream())
+}
+
+struct Context {
+ register: Option<(Ident, usize)>,
+ replaced: bool,
+ mutability: Mutability,
+}
+
+impl Context {
+ fn new(mutability: Mutability) -> Self {
+ Self { register: None, replaced: false, mutability }
+ }
+
+ fn update(&mut self, ident: &Ident, len: usize) {
+ if self.register.is_none() {
+ self.register = Some((ident.clone(), len));
+ }
+ }
+
+ fn compare_paths(&self, ident: &Ident, len: usize) -> bool {
+ match &self.register {
+ Some((i, l)) => *l == len && ident == i,
+ None => false,
+ }
+ }
+
+ fn replace_local(&mut self, local: &mut Local) -> Result<()> {
+ if let Some(Expr::Match(expr)) = local.init.as_mut().map(|(_, expr)| &mut **expr) {
+ self.replace_expr_match(expr);
+ }
+
+ if self.replaced {
+ if is_replaceable(&local.pat, false) {
+ return Err(error!(
+ local.pat,
+ "Both initializer expression and pattern are replaceable, \
+ you need to split the initializer expression into separate let bindings \
+ to avoid ambiguity"
+ ));
+ }
+ } else {
+ self.replace_pat(&mut local.pat, false);
+ }
+
+ Ok(())
+ }
+
+ fn replace_expr_let(&mut self, expr: &mut ExprLet) {
+ self.replace_pat(&mut expr.pat, true)
+ }
+
+ fn replace_expr_match(&mut self, expr: &mut ExprMatch) {
+ expr.arms.iter_mut().for_each(|Arm { pat, .. }| self.replace_pat(pat, true))
+ }
+
+ fn replace_pat(&mut self, pat: &mut Pat, allow_pat_path: bool) {
+ match pat {
+ Pat::Ident(PatIdent { subpat: Some((_, pat)), .. })
+ | Pat::Reference(PatReference { pat, .. })
+ | Pat::Box(PatBox { pat, .. })
+ | Pat::Type(PatType { pat, .. }) => self.replace_pat(pat, allow_pat_path),
+
+ Pat::Or(PatOr { cases, .. }) => {
+ cases.iter_mut().for_each(|pat| self.replace_pat(pat, allow_pat_path))
+ }
+
+ Pat::Struct(PatStruct { path, .. }) | Pat::TupleStruct(PatTupleStruct { path, .. }) => {
+ self.replace_path(path)
+ }
+ Pat::Path(PatPath { qself: None, path, .. }) if allow_pat_path => {
+ self.replace_path(path)
+ }
+ _ => {}
+ }
+ }
+
+ fn replace_path(&mut self, path: &mut Path) {
+ let len = match path.segments.len() {
+ // 1: struct
+ // 2: enum
+ len @ 1 | len @ 2 => len,
+ // other path
+ _ => return,
+ };
+
+ if self.register.is_none() || self.compare_paths(&path.segments[0].ident, len) {
+ self.update(&path.segments[0].ident, len);
+ self.replaced = true;
+ replace_ident(&mut path.segments[0].ident, self.mutability);
+ }
+ }
+}
+
+fn is_replaceable(pat: &Pat, allow_pat_path: bool) -> bool {
+ match pat {
+ Pat::Ident(PatIdent { subpat: Some((_, pat)), .. })
+ | Pat::Reference(PatReference { pat, .. })
+ | Pat::Box(PatBox { pat, .. })
+ | Pat::Type(PatType { pat, .. }) => is_replaceable(pat, allow_pat_path),
+
+ Pat::Or(PatOr { cases, .. }) => cases.iter().any(|pat| is_replaceable(pat, allow_pat_path)),
+
+ Pat::Struct(_) | Pat::TupleStruct(_) => true,
+ Pat::Path(PatPath { qself: None, .. }) => allow_pat_path,
+ _ => false,
+ }
+}
+
+fn replace_item_impl(item: &mut ItemImpl, mutability: Mutability) {
+ let PathSegment { ident, arguments } = match &mut *item.self_ty {
+ Type::Path(TypePath { qself: None, path }) => path.segments.last_mut().unwrap(),
+ _ => return,
+ };
+
+ replace_ident(ident, mutability);
+
+ let mut lifetime_name = String::from(DEFAULT_LIFETIME_NAME);
+ determine_lifetime_name(&mut lifetime_name, &item.generics.params);
+ item.items
+ .iter_mut()
+ .filter_map(|i| if let ImplItem::Method(i) = i { Some(i) } else { None })
+ .for_each(|item| determine_lifetime_name(&mut lifetime_name, &item.sig.generics.params));
+ let lifetime = Lifetime::new(&lifetime_name, Span::call_site());
+
+ insert_lifetime(&mut item.generics, lifetime.clone());
+
+ match arguments {
+ PathArguments::None => {
+ *arguments = PathArguments::AngleBracketed(syn::parse_quote!(<#lifetime>));
+ }
+ PathArguments::AngleBracketed(args) => {
+ args.args.insert(0, syn::parse_quote!(#lifetime));
+ }
+ PathArguments::Parenthesized(_) => unreachable!(),
+ }
+}
+
+fn replace_item_fn(item: &mut ItemFn, mutability: Mutability) -> Result<()> {
+ let mut visitor = FnVisitor { res: Ok(()), mutability };
+ visitor.visit_block_mut(&mut item.block);
+ visitor.res
+}
+
+fn replace_item_use(item: &mut ItemUse, mutability: Mutability) -> Result<()> {
+ let mut visitor = UseTreeVisitor { res: Ok(()), mutability };
+ visitor.visit_item_use_mut(item);
+ visitor.res
+}
+
+fn replace_ident(ident: &mut Ident, mutability: Mutability) {
+ *ident = proj_ident(ident, mutability);
+}
+
+// =================================================================================================
+// visitors
+
+struct FnVisitor {
+ res: Result<()>,
+ mutability: Mutability,
+}
+
+impl FnVisitor {
+ /// Returns the attribute name.
+ fn name(&self) -> &str {
+ if self.mutability == Mutable { "project" } else { "project_ref" }
+ }
+
+ fn visit_stmt(&mut self, node: &mut Stmt) -> Result<()> {
+ let attr = match node {
+ Stmt::Expr(Expr::Match(expr)) | Stmt::Semi(Expr::Match(expr), _) => {
+ expr.attrs.find_remove(self.name())?
+ }
+ Stmt::Local(local) => local.attrs.find_remove(self.name())?,
+ Stmt::Expr(Expr::If(expr_if)) => {
+ if let Expr::Let(_) = &*expr_if.cond {
+ expr_if.attrs.find_remove(self.name())?
+ } else {
+ None
+ }
+ }
+ _ => return Ok(()),
+ };
+ if let Some(attr) = attr {
+ parse_as_empty(&attr.tokens)?;
+ replace_stmt(node, self.mutability)?;
+ }
+ Ok(())
+ }
+}
+
+impl VisitMut for FnVisitor {
+ fn visit_stmt_mut(&mut self, node: &mut Stmt) {
+ if self.res.is_err() {
+ return;
+ }
+
+ visit_mut::visit_stmt_mut(self, node);
+
+ if let Err(e) = self.visit_stmt(node) {
+ self.res = Err(e)
+ }
+ }
+
+ fn visit_item_mut(&mut self, _: &mut Item) {
+ // Do not recurse into nested items.
+ }
+}
+
+struct UseTreeVisitor {
+ res: Result<()>,
+ mutability: Mutability,
+}
+
+impl VisitMut for UseTreeVisitor {
+ fn visit_use_tree_mut(&mut self, node: &mut UseTree) {
+ if self.res.is_err() {
+ return;
+ }
+
+ match node {
+ // Desugar `use tree::<name>` into `tree::__<name>Projection`.
+ UseTree::Name(name) => replace_ident(&mut name.ident, self.mutability),
+ UseTree::Glob(glob) => {
+ self.res =
+ Err(error!(glob, "#[project] attribute may not be used on glob imports"));
+ }
+ UseTree::Rename(rename) => {
+ // TODO: Consider allowing the projected type to be renamed by `#[project] use Foo as Bar`.
+ self.res =
+ Err(error!(rename, "#[project] attribute may not be used on renamed imports"));
+ }
+ node @ UseTree::Path(_) | node @ UseTree::Group(_) => {
+ visit_mut::visit_use_tree_mut(self, node)
+ }
+ }
+ }
+}
diff --git a/third_party/rust/pin-project-internal/src/utils.rs b/third_party/rust/pin-project-internal/src/utils.rs
new file mode 100644
index 0000000000..1890afcf36
--- /dev/null
+++ b/third_party/rust/pin-project-internal/src/utils.rs
@@ -0,0 +1,339 @@
+use std::mem;
+
+use proc_macro2::{Group, TokenStream, TokenTree};
+use quote::{format_ident, quote_spanned};
+use syn::{
+ parse::{ParseBuffer, ParseStream},
+ punctuated::Punctuated,
+ token::{self, Comma},
+ visit_mut::{self, VisitMut},
+ *,
+};
+
+pub(crate) const DEFAULT_LIFETIME_NAME: &str = "'pin";
+pub(crate) const CURRENT_PRIVATE_MODULE: &str = "__private";
+
+pub(crate) type Variants = Punctuated<Variant, token::Comma>;
+
+pub(crate) use Mutability::{Immutable, Mutable};
+
+macro_rules! error {
+ ($span:expr, $msg:expr) => {
+ syn::Error::new_spanned(&$span, $msg)
+ };
+ ($span:expr, $($tt:tt)*) => {
+ error!($span, format!($($tt)*))
+ };
+}
+
+#[derive(Clone, Copy, Eq, PartialEq)]
+pub(crate) enum Mutability {
+ Mutable,
+ Immutable,
+}
+
+/// Creates the ident of projected type from the ident of the original type.
+pub(crate) fn proj_ident(ident: &Ident, mutability: Mutability) -> Ident {
+ if mutability == Mutable {
+ format_ident!("__{}Projection", ident)
+ } else {
+ format_ident!("__{}ProjectionRef", ident)
+ }
+}
+
+/// Determines the lifetime names. Ensure it doesn't overlap with any existing lifetime names.
+pub(crate) fn determine_lifetime_name(
+ lifetime_name: &mut String,
+ generics: &Punctuated<GenericParam, Comma>,
+) {
+ let existing_lifetimes: Vec<String> = generics
+ .iter()
+ .filter_map(|param| {
+ if let GenericParam::Lifetime(LifetimeDef { lifetime, .. }) = param {
+ Some(lifetime.to_string())
+ } else {
+ None
+ }
+ })
+ .collect();
+ while existing_lifetimes.iter().any(|name| name.starts_with(&**lifetime_name)) {
+ lifetime_name.push('_');
+ }
+}
+
+/// Like `insert_lifetime`, but also generates a bound of the form
+/// `OriginalType<A, B>: 'lifetime`. Used when generating the definition
+/// of a projection type
+pub(crate) fn insert_lifetime_and_bound(
+ generics: &mut Generics,
+ lifetime: Lifetime,
+ orig_generics: &Generics,
+ orig_ident: Ident,
+) -> WherePredicate {
+ insert_lifetime(generics, lifetime.clone());
+
+ let orig_type: syn::Type = syn::parse_quote!(#orig_ident #orig_generics);
+ let mut punct = Punctuated::new();
+ punct.push(TypeParamBound::Lifetime(lifetime));
+
+ WherePredicate::Type(PredicateType {
+ lifetimes: None,
+ bounded_ty: orig_type,
+ colon_token: syn::token::Colon::default(),
+ bounds: punct,
+ })
+}
+
+/// Inserts a `lifetime` at position `0` of `generics.params`.
+pub(crate) fn insert_lifetime(generics: &mut Generics, lifetime: Lifetime) {
+ if generics.lt_token.is_none() {
+ generics.lt_token = Some(token::Lt::default())
+ }
+ if generics.gt_token.is_none() {
+ generics.gt_token = Some(token::Gt::default())
+ }
+
+ generics.params.insert(
+ 0,
+ GenericParam::Lifetime(LifetimeDef {
+ attrs: Vec::new(),
+ lifetime,
+ colon_token: None,
+ bounds: Punctuated::new(),
+ }),
+ );
+}
+
+/// Determines the visibility of the projected type and projection method.
+pub(crate) fn determine_visibility(vis: &Visibility) -> Visibility {
+ if let Visibility::Public(token) = vis {
+ syn::parse2(quote_spanned! { token.pub_token.span =>
+ pub(crate)
+ })
+ .unwrap()
+ } else {
+ vis.clone()
+ }
+}
+
+/// Check if `tokens` is an empty `TokenStream`.
+/// This is almost equivalent to `syn::parse2::<Nothing>()`,
+/// but produces a better error message and does not require ownership of `tokens`.
+pub(crate) fn parse_as_empty(tokens: &TokenStream) -> Result<()> {
+ if tokens.is_empty() { Ok(()) } else { Err(error!(tokens, "unexpected token: {}", tokens)) }
+}
+
+// =================================================================================================
+// extension traits
+
+pub(crate) trait SliceExt {
+ fn position_exact(&self, ident: &str) -> Result<Option<usize>>;
+ fn find(&self, ident: &str) -> Option<&Attribute>;
+ fn find_exact(&self, ident: &str) -> Result<Option<&Attribute>>;
+}
+
+pub(crate) trait VecExt {
+ fn find_remove(&mut self, ident: &str) -> Result<Option<Attribute>>;
+}
+
+impl SliceExt for [Attribute] {
+ fn position_exact(&self, ident: &str) -> Result<Option<usize>> {
+ self.iter()
+ .try_fold((0, None), |(i, mut prev), attr| {
+ if attr.path.is_ident(ident) {
+ if prev.is_some() {
+ return Err(error!(attr, "duplicate #[{}] attribute", ident));
+ }
+ parse_as_empty(&attr.tokens)?;
+ prev = Some(i);
+ }
+ Ok((i + 1, prev))
+ })
+ .map(|(_, pos)| pos)
+ }
+
+ fn find(&self, ident: &str) -> Option<&Attribute> {
+ self.iter().position(|attr| attr.path.is_ident(ident)).and_then(|i| self.get(i))
+ }
+
+ fn find_exact(&self, ident: &str) -> Result<Option<&Attribute>> {
+ self.position_exact(ident).map(|pos| pos.and_then(|i| self.get(i)))
+ }
+}
+
+impl VecExt for Vec<Attribute> {
+ fn find_remove(&mut self, ident: &str) -> Result<Option<Attribute>> {
+ self.position_exact(ident).map(|pos| pos.map(|i| self.remove(i)))
+ }
+}
+
+pub(crate) trait ParseBufferExt<'a> {
+ fn parenthesized(self) -> Result<ParseBuffer<'a>>;
+}
+
+impl<'a> ParseBufferExt<'a> for ParseStream<'a> {
+ fn parenthesized(self) -> Result<ParseBuffer<'a>> {
+ let content;
+ let _: token::Paren = syn::parenthesized!(content in self);
+ Ok(content)
+ }
+}
+
+impl<'a> ParseBufferExt<'a> for ParseBuffer<'a> {
+ fn parenthesized(self) -> Result<ParseBuffer<'a>> {
+ let content;
+ let _: token::Paren = syn::parenthesized!(content in self);
+ Ok(content)
+ }
+}
+
+// =================================================================================================
+// visitors
+
+// Replace `self`/`Self` with `__self`/`self_ty`.
+// Based on https://github.com/dtolnay/async-trait/blob/0.1.22/src/receiver.rs
+
+pub(crate) struct ReplaceReceiver<'a> {
+ self_ty: &'a Type,
+}
+
+impl<'a> ReplaceReceiver<'a> {
+ pub(crate) fn new(self_ty: &'a Type) -> Self {
+ Self { self_ty }
+ }
+
+ fn self_to_qself(&mut self, qself: &mut Option<QSelf>, path: &mut Path) {
+ if path.leading_colon.is_some() {
+ return;
+ }
+
+ let first = &path.segments[0];
+ if first.ident != "Self" || !first.arguments.is_empty() {
+ return;
+ }
+
+ if path.segments.len() == 1 {
+ self.self_to_expr_path(path);
+ return;
+ }
+
+ *qself = Some(QSelf {
+ lt_token: token::Lt::default(),
+ ty: Box::new(self.self_ty.clone()),
+ position: 0,
+ as_token: None,
+ gt_token: token::Gt::default(),
+ });
+
+ match path.segments.pairs().next().unwrap().punct() {
+ Some(&&colon) => path.leading_colon = Some(colon),
+ None => return,
+ }
+
+ let segments = mem::replace(&mut path.segments, Punctuated::new());
+ path.segments = segments.into_pairs().skip(1).collect();
+ }
+
+ fn self_to_expr_path(&self, path: &mut Path) {
+ if let Type::Path(self_ty) = &self.self_ty {
+ *path = self_ty.path.clone();
+ for segment in &mut path.segments {
+ if let PathArguments::AngleBracketed(bracketed) = &mut segment.arguments {
+ if bracketed.colon2_token.is_none() && !bracketed.args.is_empty() {
+ bracketed.colon2_token = Some(token::Colon2::default());
+ }
+ }
+ }
+ } else {
+ let span = path.segments[0].ident.span();
+ let msg = "Self type of this impl is unsupported in expression position";
+ let error = Error::new(span, msg).to_compile_error();
+ *path = parse_quote!(::core::marker::PhantomData::<#error>);
+ }
+ }
+}
+
+impl VisitMut for ReplaceReceiver<'_> {
+ // `Self` -> `Receiver`
+ fn visit_type_mut(&mut self, ty: &mut Type) {
+ if let Type::Path(node) = ty {
+ if node.qself.is_none() && node.path.is_ident("Self") {
+ *ty = self.self_ty.clone();
+ } else {
+ self.visit_type_path_mut(node);
+ }
+ } else {
+ visit_mut::visit_type_mut(self, ty);
+ }
+ }
+
+ // `Self::Assoc` -> `<Receiver>::Assoc`
+ fn visit_type_path_mut(&mut self, ty: &mut TypePath) {
+ if ty.qself.is_none() {
+ self.self_to_qself(&mut ty.qself, &mut ty.path);
+ }
+ visit_mut::visit_type_path_mut(self, ty);
+ }
+
+ // `Self::method` -> `<Receiver>::method`
+ fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) {
+ if expr.qself.is_none() {
+ prepend_underscore_to_self(&mut expr.path.segments[0].ident);
+ self.self_to_qself(&mut expr.qself, &mut expr.path);
+ }
+ visit_mut::visit_expr_path_mut(self, expr);
+ }
+
+ fn visit_expr_struct_mut(&mut self, expr: &mut ExprStruct) {
+ if expr.path.is_ident("Self") {
+ self.self_to_expr_path(&mut expr.path);
+ }
+ visit_mut::visit_expr_struct_mut(self, expr);
+ }
+
+ fn visit_macro_mut(&mut self, node: &mut Macro) {
+ // We can't tell in general whether `self` inside a macro invocation
+ // refers to the self in the argument list or a different self
+ // introduced within the macro. Heuristic: if the macro input contains
+ // `fn`, then `self` is more likely to refer to something other than the
+ // outer function's self argument.
+ if !contains_fn(node.tokens.clone()) {
+ node.tokens = fold_token_stream(node.tokens.clone());
+ }
+ }
+
+ fn visit_item_mut(&mut self, _: &mut Item) {
+ // Do not recurse into nested items.
+ }
+}
+
+fn contains_fn(tokens: TokenStream) -> bool {
+ tokens.into_iter().any(|tt| match tt {
+ TokenTree::Ident(ident) => ident == "fn",
+ TokenTree::Group(group) => contains_fn(group.stream()),
+ _ => false,
+ })
+}
+
+fn fold_token_stream(tokens: TokenStream) -> TokenStream {
+ tokens
+ .into_iter()
+ .map(|tt| match tt {
+ TokenTree::Ident(mut ident) => {
+ prepend_underscore_to_self(&mut ident);
+ TokenTree::Ident(ident)
+ }
+ TokenTree::Group(group) => {
+ let content = fold_token_stream(group.stream());
+ TokenTree::Group(Group::new(group.delimiter(), content))
+ }
+ other => other,
+ })
+ .collect()
+}
+
+pub(crate) fn prepend_underscore_to_self(ident: &mut Ident) {
+ if ident == "self" {
+ *ident = Ident::new("__self", ident.span());
+ }
+}