Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
macro_rules! format_err {
($span:expr, $msg:expr $(,)?) => {
syn::Error::new_spanned(&$span as &dyn quote::ToTokens, &$msg as &dyn std::fmt::Display)
};
($span:expr, $($tt:tt)*) => {
format_err!($span, format!($($tt)*))
};
}
macro_rules! bail {
($($tt:tt)*) => {
return Err(format_err!($($tt)*))
};
}

577
vendor/pin-project-internal/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,577 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! Implementation detail of the `pin-project` crate. - **do not use directly**
#![doc(test(
no_crate_inject,
attr(
deny(warnings, rust_2018_idioms, single_use_lifetimes),
allow(dead_code, unused_variables)
)
))]
#![forbid(unsafe_code)]
#![allow(clippy::needless_doctest_main)]
#[macro_use]
mod error;
#[macro_use]
mod utils;
mod pin_project;
mod pinned_drop;
use proc_macro::TokenStream;
/// An attribute that creates projection types covering all the fields of
/// struct or enum.
///
/// This attribute creates projection types according to the following rules:
///
/// - For the fields that use `#[pin]` attribute, create the pinned reference to
/// the field.
/// - For the other fields, create a normal reference to the field.
///
/// And 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<'_>;
/// # }
/// ```
///
/// By passing an argument with the same name as the method to the attribute,
/// you can name the projection type returned from the method. This allows you
/// to use pattern matching on the projected types.
///
/// ```
/// # use pin_project::pin_project;
/// # use std::pin::Pin;
/// #[pin_project(project = EnumProj)]
/// enum Enum<T> {
/// Variant(#[pin] T),
/// }
///
/// impl<T> Enum<T> {
/// fn method(self: Pin<&mut Self>) {
/// let this: EnumProj<'_, T> = self.project();
/// match this {
/// EnumProj::Variant(x) => {
/// let _: Pin<&mut T> = x;
/// }
/// }
/// }
/// }
/// ```
///
/// Note that the projection types returned by `project` and `project_ref` have
/// an additional lifetime at the beginning of generics.
///
/// ```text
/// let this: EnumProj<'_, T> = self.project();
/// ^^
/// ```
///
/// The visibility of the projected types and projection methods is based on the
/// original type. However, if the visibility of the original type is `pub`, the
/// visibility of the projected types and the projection methods is downgraded
/// to `pub(crate)`.
///
/// # Safety
///
/// This attribute is completely safe. In the absence of other `unsafe` code
/// *that you write*, it is impossible to cause [undefined
/// behavior][undefined-behavior] with this attribute.
///
/// This is accomplished by enforcing the four requirements for pin projection
/// stated in [the Rust documentation][pin-projection]:
///
/// 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 attempt to provide an [`Unpin`] 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 manual [`Unpin`] impl, you can do so via the
/// [`UnsafeUnpin`][unsafe-unpin] 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:
///
/// ```
/// struct MyStruct {}
/// trait MyStructMustNotImplDrop {}
/// # #[allow(unknown_lints, drop_bounds)]
/// 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 an impl
/// with [`#[pinned_drop]`][pinned-drop]. This impl 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][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 way 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)]`][repr-packed]
/// types. Attempting to use this attribute on a `#[repr(packed)]` type results
/// in a compile-time error.
///
/// # Examples
///
/// `#[pin_project]` can be used on structs and enums.
///
/// ```
/// use std::pin::Pin;
///
/// use pin_project::pin_project;
///
/// #[pin_project]
/// struct Struct<T, U> {
/// #[pin]
/// pinned: T,
/// unpinned: U,
/// }
///
/// impl<T, U> Struct<T, U> {
/// fn method(self: Pin<&mut Self>) {
/// let this = self.project();
/// let _: Pin<&mut T> = this.pinned;
/// let _: &mut U = this.unpinned;
/// }
/// }
/// ```
///
/// ```
/// use std::pin::Pin;
///
/// use pin_project::pin_project;
///
/// #[pin_project]
/// struct TupleStruct<T, U>(#[pin] T, U);
///
/// impl<T, U> TupleStruct<T, U> {
/// fn method(self: Pin<&mut Self>) {
/// let this = self.project();
/// let _: Pin<&mut T> = this.0;
/// let _: &mut U = this.1;
/// }
/// }
/// ```
///
/// To use `#[pin_project]` on enums, you need to name the projection type
/// returned from the method.
///
/// ```
/// use std::pin::Pin;
///
/// use pin_project::pin_project;
///
/// #[pin_project(project = EnumProj)]
/// enum Enum<T, U> {
/// Tuple(#[pin] T),
/// Struct { field: U },
/// Unit,
/// }
///
/// impl<T, U> Enum<T, U> {
/// fn method(self: Pin<&mut Self>) {
/// match self.project() {
/// EnumProj::Tuple(x) => {
/// let _: Pin<&mut T> = x;
/// }
/// EnumProj::Struct { field } => {
/// let _: &mut U = field;
/// }
/// EnumProj::Unit => {}
/// }
/// }
/// }
/// ```
///
/// When `#[pin_project]` is used on enums, only named projection types and
/// methods are generated because there is no way to access variants of
/// projected types without naming it.
/// For example, in the above example, only the `project` method is generated,
/// and the `project_ref` method is not generated.
/// (When `#[pin_project]` is used on structs, both methods are always generated.)
///
/// ```compile_fail,E0599
/// # use pin_project::pin_project;
/// # use std::pin::Pin;
/// #
/// # #[pin_project(project = EnumProj)]
/// # enum Enum<T, U> {
/// # Tuple(#[pin] T),
/// # Struct { field: U },
/// # Unit,
/// # }
/// #
/// impl<T, U> Enum<T, U> {
/// fn call_project_ref(self: Pin<&Self>) {
/// let _this = self.project_ref();
/// //~^ ERROR no method named `project_ref` found for struct `Pin<&Enum<T, U>>` in the current scope
/// }
/// }
/// ```
///
/// If you want to call `.project()` multiple times or later use the
/// original [`Pin`] type, it needs to use [`.as_mut()`][`Pin::as_mut`] to avoid
/// consuming the [`Pin`].
///
/// ```
/// use std::pin::Pin;
///
/// use pin_project::pin_project;
///
/// #[pin_project]
/// struct Struct<T> {
/// #[pin]
/// field: T,
/// }
///
/// impl<T> Struct<T> {
/// fn call_project_twice(mut self: Pin<&mut Self>) {
/// // `project` consumes `self`, so reborrow the `Pin<&mut Self>` via `as_mut`.
/// self.as_mut().project();
/// self.as_mut().project();
/// }
/// }
/// ```
///
/// # `!Unpin`
///
/// If you want to ensure that [`Unpin`] is not implemented, use the `!Unpin`
/// argument to `#[pin_project]`.
///
/// ```
/// use pin_project::pin_project;
///
/// #[pin_project(!Unpin)]
/// struct Struct<T> {
/// field: T,
/// }
/// ```
///
/// This is equivalent to using `#[pin]` attribute for the [`PhantomPinned`]
/// field.
///
/// ```
/// use std::marker::PhantomPinned;
///
/// use pin_project::pin_project;
///
/// #[pin_project]
/// struct Struct<T> {
/// field: T,
/// #[pin] // <------ This `#[pin]` is required to make `Struct` to `!Unpin`.
/// _pin: PhantomPinned,
/// }
/// ```
///
/// Note that using [`PhantomPinned`] without `#[pin]` attribute has no effect.
///
/// # `UnsafeUnpin`
///
/// If you want to implement [`Unpin`] manually, you must use the `UnsafeUnpin`
/// argument to `#[pin_project]`.
///
/// ```
/// use pin_project::{UnsafeUnpin, pin_project};
///
/// #[pin_project(UnsafeUnpin)]
/// struct Struct<T, U> {
/// #[pin]
/// pinned: T,
/// unpinned: U,
/// }
///
/// unsafe impl<T: Unpin, U> UnsafeUnpin for Struct<T, U> {}
/// ```
///
/// 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`.
///
/// ```
/// # use std::pin::Pin;
/// pub trait PinnedDrop {
/// fn drop(self: Pin<&mut Self>);
/// }
/// ```
///
/// `#[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:
///
/// ```
/// use std::{fmt::Debug, pin::Pin};
///
/// use pin_project::{pin_project, pinned_drop};
///
/// #[pin_project(PinnedDrop)]
/// struct PrintOnDrop<T: Debug, U: Debug> {
/// #[pin]
/// pinned_field: T,
/// unpin_field: U,
/// }
///
/// #[pinned_drop]
/// impl<T: Debug, U: Debug> PinnedDrop for PrintOnDrop<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 = PrintOnDrop { pinned_field: true, unpin_field: 40 };
/// }
/// ```
///
/// See also [`#[pinned_drop]`][macro@pinned_drop] attribute.
///
/// # `project_replace` method
///
/// In addition to the `project` and `project_ref` methods which are always
/// provided when you use the `#[pin_project]` attribute, there is a third
/// method, `project_replace` which can be useful in some situations. It is
/// equivalent to [`Pin::set`], except that the unpinned fields are moved and
/// returned, instead of being dropped in-place.
///
/// ```
/// # use std::pin::Pin;
/// # type ProjectionOwned = ();
/// # trait Dox {
/// fn project_replace(self: Pin<&mut Self>, other: Self) -> ProjectionOwned;
/// # }
/// ```
///
/// The `ProjectionOwned` type is identical to the `Self` type, except that
/// all pinned fields have been replaced by equivalent [`PhantomData`] types.
///
/// This method is opt-in, because it is only supported for [`Sized`] types, and
/// because it is incompatible with the [`#[pinned_drop]`][pinned-drop]
/// attribute described above. It can be enabled by using
/// `#[pin_project(project_replace)]`.
///
/// For example:
///
/// ```
/// use std::{marker::PhantomData, pin::Pin};
///
/// use pin_project::pin_project;
///
/// #[pin_project(project_replace)]
/// struct Struct<T, U> {
/// #[pin]
/// pinned_field: T,
/// unpinned_field: U,
/// }
///
/// impl<T, U> Struct<T, U> {
/// fn method(self: Pin<&mut Self>, other: Self) {
/// let this = self.project_replace(other);
/// let _: U = this.unpinned_field;
/// let _: PhantomData<T> = this.pinned_field;
/// }
/// }
/// ```
///
/// By passing the value to the `project_replace` argument, you can name the
/// returned type of the `project_replace` method. This is necessary whenever
/// destructuring the return type of the `project_replace` method, and work in exactly
/// the same way as the `project` and `project_ref` arguments.
///
/// ```
/// use pin_project::pin_project;
///
/// #[pin_project(project_replace = EnumProjOwn)]
/// enum Enum<T, U> {
/// A {
/// #[pin]
/// pinned_field: T,
/// unpinned_field: U,
/// },
/// B,
/// }
///
/// let mut x = Box::pin(Enum::A { pinned_field: 42, unpinned_field: "hello" });
///
/// match x.as_mut().project_replace(Enum::B) {
/// EnumProjOwn::A { unpinned_field, .. } => assert_eq!(unpinned_field, "hello"),
/// EnumProjOwn::B => unreachable!(),
/// }
/// ```
///
/// [`PhantomData`]: core::marker::PhantomData
/// [`PhantomPinned`]: core::marker::PhantomPinned
/// [`Pin::as_mut`]: core::pin::Pin::as_mut
/// [`Pin::set`]: core::pin::Pin::set
/// [`Pin`]: core::pin::Pin
/// [`UnsafeUnpin`]: https://docs.rs/pin-project/latest/pin_project/trait.UnsafeUnpin.html
/// [drop-guarantee]: core::pin#drop-guarantee
/// [pin-projection]: core::pin#projections-and-structural-pinning
/// [pinned-drop]: macro@pin_project#pinned_drop
/// [repr-packed]: https://doc.rust-lang.org/nomicon/other-reprs.html#reprpacked
/// [undefined-behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
/// [unsafe-unpin]: macro@pin_project#unsafeunpin
#[proc_macro_attribute]
pub fn pin_project(args: TokenStream, input: TokenStream) -> TokenStream {
pin_project::attribute(&args.into(), input.into()).into()
}
/// An attribute used for custom implementations of [`Drop`].
///
/// This attribute is used in conjunction with the `PinnedDrop` argument to
/// the [`#[pin_project]`][macro@pin_project] attribute.
///
/// The impl block annotated with this attribute acts just like a normal
/// [`Drop`] impl, except for the following two:
///
/// - `drop` method takes [`Pin`]`<&mut Self>`
/// - Name of the trait is `PinnedDrop`.
///
/// ```
/// # use std::pin::Pin;
/// pub trait PinnedDrop {
/// fn drop(self: Pin<&mut Self>);
/// }
/// ```
///
/// `#[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`].
///
/// # Examples
///
/// ```
/// use std::pin::Pin;
///
/// use pin_project::{pin_project, pinned_drop};
///
/// #[pin_project(PinnedDrop)]
/// struct PrintOnDrop {
/// #[pin]
/// field: u8,
/// }
///
/// #[pinned_drop]
/// impl PinnedDrop for PrintOnDrop {
/// fn drop(self: Pin<&mut Self>) {
/// println!("Dropping: {}", self.field);
/// }
/// }
///
/// fn main() {
/// let _x = PrintOnDrop { field: 50 };
/// }
/// ```
///
/// See also ["pinned-drop" section of `#[pin_project]` attribute][pinned-drop].
///
/// # Why `#[pinned_drop]` attribute is needed?
///
/// Implementing `PinnedDrop::drop` is safe, but calling it is not safe.
/// This is because destructors can be called multiple times in safe code and
/// [double dropping is unsound][rust-lang/rust#62360].
///
/// Ideally, it would be desirable to be able to forbid manual calls in
/// the same way as [`Drop::drop`], but the library cannot do it. So, by using
/// macros and replacing them with private traits like the following,
/// this crate prevent users from calling `PinnedDrop::drop` in safe code.
///
/// ```
/// # use std::pin::Pin;
/// pub trait PinnedDrop {
/// unsafe fn drop(self: Pin<&mut Self>);
/// }
/// ```
///
/// This allows implementing [`Drop`] safely using `#[pinned_drop]`.
/// Also by using the [`drop`] function just like dropping a type that directly
/// implements [`Drop`], can drop safely a type that implements `PinnedDrop`.
///
/// [rust-lang/rust#62360]: https://github.com/rust-lang/rust/pull/62360
/// [`Pin`]: core::pin::Pin
/// [pinned-drop]: macro@pin_project#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()
}
// Not public API.
#[doc(hidden)]
#[proc_macro_derive(__PinProjectInternalDerive, attributes(pin))]
pub fn __pin_project_internal_derive(input: TokenStream) -> TokenStream {
pin_project::derive(input.into()).into()
}

View File

@@ -0,0 +1,250 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{
Attribute, Error, Ident, Result, Token,
parse::{Parse, ParseStream},
spanned::Spanned as _,
};
use super::PIN;
use crate::utils::{ParseBufferExt as _, SliceExt as _};
pub(super) fn parse_args(attrs: &[Attribute]) -> Result<Args> {
// `(__private(<args>))` -> `<args>`
struct Input(Option<TokenStream>);
impl Parse for Input {
fn parse(input: ParseStream<'_>) -> Result<Self> {
Ok(Self((|| {
let private = input.parse::<Ident>().ok()?;
if private == "__private" {
input.parenthesized().ok()?.parse::<TokenStream>().ok()
} else {
None
}
})()))
}
}
if let Some(attr) = attrs.find("pin_project") {
bail!(attr, "duplicate #[pin_project] attribute");
}
let mut attrs = attrs.iter().filter(|attr| attr.path().is_ident(PIN));
let prev = if let Some(attr) = attrs.next() {
(attr, syn::parse2::<Input>(attr.meta.require_list()?.tokens.clone())?.0)
} else {
// This only fails if another macro removes `#[pin]`.
bail!(TokenStream::new(), "#[pin_project] attribute has been removed");
};
if let Some(attr) = attrs.next() {
let (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.
// So, use the span of `prev_attr` if it is not a valid attribute.
let res = syn::parse2::<Input>(attr.meta.require_list()?.tokens.clone())?.0;
let span = match (prev_res, res) {
(Some(_), _) => attr,
(None, _) => prev_attr,
};
bail!(span, "duplicate #[pin] attribute");
}
// This `unwrap` only fails if another macro removes `#[pin]` and inserts own `#[pin]`.
syn::parse2(prev.1.unwrap())
}
pub(super) struct Args {
/// `PinnedDrop` argument.
pub(super) pinned_drop: Option<Span>,
/// `UnsafeUnpin` or `!Unpin` argument.
pub(super) unpin_impl: UnpinImpl,
/// `project = <ident>` argument.
pub(super) project: Option<Ident>,
/// `project_ref = <ident>` argument.
pub(super) project_ref: Option<Ident>,
/// `project_replace [= <ident>]` argument.
pub(super) project_replace: ProjReplace,
}
impl Parse for Args {
fn parse(input: ParseStream<'_>) -> Result<Self> {
mod kw {
syn::custom_keyword!(Unpin);
}
/// Parses `= <value>` in `<name> = <value>` and returns value and span of name-value pair.
fn parse_value(
input: ParseStream<'_>,
name: &Ident,
has_prev: bool,
) -> Result<(Ident, TokenStream)> {
if input.is_empty() {
bail!(name, "expected `{0} = <identifier>`, found `{0}`", name);
}
let eq_token: Token![=] = input.parse()?;
if input.is_empty() {
let span = quote!(#name #eq_token);
bail!(span, "expected `{0} = <identifier>`, found `{0} =`", name);
}
let value: Ident = input.parse()?;
let span = quote!(#name #value);
if has_prev {
bail!(span, "duplicate `{}` argument", name);
}
Ok((value, span))
}
let mut pinned_drop = None;
let mut unsafe_unpin = None;
let mut not_unpin = None;
let mut project = None;
let mut project_ref = None;
let mut project_replace_value = None;
let mut project_replace_span = None;
while !input.is_empty() {
if input.peek(Token![!]) {
let bang: Token![!] = input.parse()?;
if input.is_empty() {
bail!(bang, "expected `!Unpin`, found `!`");
}
let unpin: kw::Unpin = input.parse()?;
let span = quote!(#bang #unpin);
if not_unpin.replace(span.span()).is_some() {
bail!(span, "duplicate `!Unpin` argument");
}
} else {
let token = input.parse::<Ident>()?;
match &*token.to_string() {
"PinnedDrop" => {
if pinned_drop.replace(token.span()).is_some() {
bail!(token, "duplicate `PinnedDrop` argument");
}
}
"UnsafeUnpin" => {
if unsafe_unpin.replace(token.span()).is_some() {
bail!(token, "duplicate `UnsafeUnpin` argument");
}
}
"project" => {
project = Some(parse_value(input, &token, project.is_some())?.0);
}
"project_ref" => {
project_ref = Some(parse_value(input, &token, project_ref.is_some())?.0);
}
"project_replace" => {
if input.peek(Token![=]) {
let (value, span) =
parse_value(input, &token, project_replace_span.is_some())?;
project_replace_value = Some(value);
project_replace_span = Some(span.span());
} else if project_replace_span.is_some() {
bail!(token, "duplicate `project_replace` argument");
} else {
project_replace_span = Some(token.span());
}
}
"Replace" => {
bail!(
token,
"`Replace` argument was removed, use `project_replace` argument instead"
);
}
_ => bail!(token, "unexpected argument: {}", token),
}
}
if input.is_empty() {
break;
}
let _: Token![,] = input.parse()?;
}
if project.is_some() || project_ref.is_some() {
if project == project_ref {
bail!(
project_ref,
"name `{}` is already specified by `project` argument",
project_ref.as_ref().unwrap()
);
}
if let Some(ident) = &project_replace_value {
if project == project_replace_value {
bail!(ident, "name `{}` is already specified by `project` argument", ident);
} else if project_ref == project_replace_value {
bail!(ident, "name `{}` is already specified by `project_ref` argument", ident);
}
}
}
if let Some(span) = pinned_drop {
if project_replace_span.is_some() {
return Err(Error::new(
span,
"arguments `PinnedDrop` and `project_replace` are mutually exclusive",
));
}
}
let project_replace = match (project_replace_span, project_replace_value) {
(None, _) => ProjReplace::None,
(Some(span), Some(ident)) => ProjReplace::Named { ident, span },
(Some(span), None) => ProjReplace::Unnamed { span },
};
let unpin_impl = match (unsafe_unpin, not_unpin) {
(None, None) => UnpinImpl::Default,
(Some(span), None) => UnpinImpl::Unsafe(span),
(None, Some(span)) => UnpinImpl::Negative(span),
(Some(span), Some(_)) => {
return Err(Error::new(
span,
"arguments `UnsafeUnpin` and `!Unpin` are mutually exclusive",
));
}
};
Ok(Self { pinned_drop, unpin_impl, project, project_ref, project_replace })
}
}
/// `UnsafeUnpin` or `!Unpin` argument.
#[derive(Clone, Copy)]
pub(super) enum UnpinImpl {
Default,
/// `UnsafeUnpin`.
Unsafe(Span),
/// `!Unpin`.
Negative(Span),
}
/// `project_replace [= <ident>]` argument.
pub(super) enum ProjReplace {
None,
/// `project_replace`.
Unnamed {
span: Span,
},
/// `project_replace = <ident>`.
Named {
span: Span,
ident: Ident,
},
}
impl ProjReplace {
/// Return the span of this argument.
pub(super) fn span(&self) -> Option<Span> {
match self {
Self::None => None,
Self::Named { span, .. } | Self::Unnamed { span, .. } => Some(*span),
}
}
pub(super) fn ident(&self) -> Option<&Ident> {
if let Self::Named { ident, .. } = self { Some(ident) } else { None }
}
}

View File

@@ -0,0 +1,66 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use proc_macro2::TokenStream;
use quote::quote;
use syn::{
Attribute, Result, Token, Visibility,
parse::{Parse, ParseStream},
};
use super::PIN;
use crate::utils::SliceExt as _;
// 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 { attrs, body } = syn::parse2(input)?;
Ok(quote! {
#(#attrs)*
#[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.
#[pin(__private(#args))]
#body
})
}
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.
bail!(
input.parse::<TokenStream>()?,
"#[pin_project] attribute may only be used on structs or enums"
);
} else if let Some(attr) = attrs.find(PIN) {
bail!(attr, "#[pin] attribute may only be used on fields of structs or variants");
} else if let Some(attr) = attrs.find("pin_project") {
bail!(attr, "duplicate #[pin_project] attribute");
}
Ok(Self { attrs, body: input.parse()? })
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
mod args;
mod attribute;
mod derive;
use proc_macro2::TokenStream;
use syn::Error;
/// 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(Error::into_compile_error)
}
pub(crate) fn derive(input: TokenStream) -> TokenStream {
derive::parse_derive(input).unwrap_or_else(Error::into_compile_error)
}

View File

@@ -0,0 +1,233 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use proc_macro2::{Span, TokenStream};
use quote::{ToTokens as _, format_ident, quote};
use syn::{
Error, FnArg, GenericArgument, Ident, ImplItem, ItemImpl, Pat, PatIdent, PatType, Path,
PathArguments, Result, ReturnType, Signature, Token, Type, TypePath, TypeReference,
parse_quote, spanned::Spanned as _, token::Colon, visit_mut::VisitMut as _,
};
use crate::utils::{ReplaceReceiver, SliceExt as _};
pub(crate) fn attribute(args: &TokenStream, mut input: ItemImpl) -> TokenStream {
let res = (|| -> Result<()> {
if !args.is_empty() {
bail!(args, "unexpected argument: `{}`", args)
}
validate_impl(&input)?;
expand_impl(&mut input);
Ok(())
})();
if let Err(e) = res {
let mut tokens = e.to_compile_error();
if let Type::Path(self_ty) = &*input.self_ty {
let (impl_generics, _, where_clause) = input.generics.split_for_impl();
// Generate a dummy impl of `PinnedDrop`.
// 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.
//
// However, if `input.self_ty` is not Type::Path, there is a high possibility that
// the type does not exist (since #[pin_project] can only be used on struct/enum
// definitions), so do not generate a dummy impl.
tokens.extend(quote! {
impl #impl_generics ::pin_project::__private::PinnedDrop for #self_ty
#where_clause
{
unsafe fn drop(self: ::pin_project::__private::Pin<&mut Self>) {}
}
});
}
tokens
} else {
input.into_token_stream()
}
}
/// Validates the signature of given `PinnedDrop` impl.
fn validate_impl(item: &ItemImpl) -> Result<()> {
const INVALID_ITEM: &str =
"#[pinned_drop] may only be used on implementation for the `PinnedDrop` trait";
if let Some(attr) = item.attrs.find("pinned_drop") {
bail!(attr, "duplicate #[pinned_drop] attribute");
}
if let Some((_, path, _)) = &item.trait_ {
if !path.is_ident("PinnedDrop") {
bail!(path, INVALID_ITEM);
}
} else {
bail!(item.self_ty, INVALID_ITEM);
}
if item.unsafety.is_some() {
bail!(item.unsafety, "implementing the trait `PinnedDrop` is not unsafe");
}
if item.items.is_empty() {
bail!(item, "not all trait items implemented, missing: `drop`");
}
match &*item.self_ty {
Type::Path(_) => {}
ty => {
bail!(ty, "implementing the trait `PinnedDrop` on this type is unsupported");
}
}
item.items.iter().enumerate().try_for_each(|(i, item)| match item {
ImplItem::Const(item) => {
bail!(item, "const `{}` is not a member of trait `PinnedDrop`", item.ident)
}
ImplItem::Type(item) => {
bail!(item, "type `{}` is not a member of trait `PinnedDrop`", item.ident)
}
ImplItem::Fn(method) => {
validate_sig(&method.sig)?;
if i == 0 { Ok(()) } else { bail!(method, "duplicate definitions with name `drop`") }
}
_ => unreachable!("unexpected ImplItem"),
})
}
/// Validates the signature of given `PinnedDrop::drop` method.
///
/// The correct signature is: `(mut) self: (<path>::)Pin<&mut Self>`
fn validate_sig(sig: &Signature) -> 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 sig.ident != "drop" {
bail!(sig.ident, "method `{}` is not a member of trait `PinnedDrop`", sig.ident);
}
if let ReturnType::Type(_, ty) = &sig.output {
match &**ty {
Type::Tuple(ty) if ty.elems.is_empty() => {}
_ => bail!(ty, "method `drop` must return the unit type"),
}
}
match sig.inputs.len() {
1 => {}
0 => return Err(Error::new(sig.paren_token.span.join(), INVALID_ARGUMENT)),
_ => bail!(sig.inputs, INVALID_ARGUMENT),
}
if let Some(arg) = sig.receiver() {
// (mut) self: <path>
if let Some(path) = get_ty_path(&arg.ty) {
let ty =
path.segments.last().expect("type paths should always have at least one segment");
if let PathArguments::AngleBracketed(args) = &ty.arguments {
// (mut) self: (<path>::)<ty><&mut <elem>..>
if let Some(GenericArgument::Type(Type::Reference(TypeReference {
mutability: Some(_),
elem,
..
}))) = args.args.first()
{
// (mut) self: (<path>::)Pin<&mut Self>
if args.args.len() == 1
&& ty.ident == "Pin"
&& get_ty_path(elem).map_or(false, |path| path.is_ident("Self"))
{
if sig.unsafety.is_some() {
bail!(sig.unsafety, "implementing the method `drop` is not unsafe");
}
return Ok(());
}
}
}
}
}
bail!(sig.inputs[0], INVALID_ARGUMENT)
}
// from:
//
// fn drop(self: Pin<&mut Self>) {
// // ...
// }
//
// into:
//
// unsafe fn drop(self: Pin<&mut Self>) {
// fn __drop_inner<T>(__self: Pin<&mut Foo<'_, T>>) {
// fn __drop_inner() {}
// // ...
// }
// __drop_inner(self);
// }
//
fn expand_impl(item: &mut ItemImpl) {
// `PinnedDrop` is a private trait and should not appear in docs.
item.attrs.push(parse_quote!(#[doc(hidden)]));
let path = &mut item.trait_.as_mut().expect("unexpected inherent impl").1;
*path = parse_quote_spanned! { Span::call_site().located_at(path.span()) =>
::pin_project::__private::PinnedDrop
};
let method =
if let ImplItem::Fn(method) = &mut item.items[0] { method } else { unreachable!() };
// `fn drop(mut self: Pin<&mut Self>)` -> `fn __drop_inner<T>(mut __self: Pin<&mut Receiver>)`
let drop_inner = {
let mut drop_inner = method.clone();
let ident = format_ident!("__drop_inner");
// Add a dummy `__drop_inner` function to prevent users call outer `__drop_inner`.
drop_inner.block.stmts.insert(0, parse_quote!(fn #ident() {}));
drop_inner.sig.ident = ident;
drop_inner.sig.generics = item.generics.clone();
let receiver = drop_inner.sig.receiver().expect("drop() should have a receiver").clone();
let pat = Box::new(Pat::Ident(PatIdent {
attrs: vec![],
by_ref: None,
mutability: receiver.mutability,
ident: Ident::new("__self", receiver.self_token.span()),
subpat: None,
}));
drop_inner.sig.inputs[0] = FnArg::Typed(PatType {
attrs: receiver.attrs,
pat,
colon_token: Colon::default(),
ty: receiver.ty,
});
let self_ty = if let Type::Path(ty) = &*item.self_ty { ty } else { unreachable!() };
let mut visitor = ReplaceReceiver(self_ty);
visitor.visit_signature_mut(&mut drop_inner.sig);
visitor.visit_block_mut(&mut drop_inner.block);
drop_inner
};
// `fn drop(mut self: Pin<&mut Self>)` -> `unsafe fn drop(self: Pin<&mut Self>)`
method.sig.unsafety = Some(<Token![unsafe]>::default());
let self_token = if let FnArg::Receiver(ref mut rec) = method.sig.inputs[0] {
rec.mutability = None;
&rec.self_token
} else {
panic!("drop() should have a receiver")
};
method.block.stmts = parse_quote! {
#[allow(
clippy::missing_const_for_fn,
clippy::needless_pass_by_value, // This lint does not warn the receiver.
clippy::single_call_fn
)]
#drop_inner
__drop_inner(#self_token);
};
}

370
vendor/pin-project-internal/src/utils.rs vendored Normal file
View File

@@ -0,0 +1,370 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
use std::mem;
use proc_macro2::{Group, Spacing, Span, TokenStream, TokenTree};
use quote::{ToTokens, quote, quote_spanned};
use syn::{
Attribute, ExprPath, ExprStruct, Generics, Ident, Item, Lifetime, LifetimeParam, Macro,
PatStruct, PatTupleStruct, Path, PathArguments, PredicateType, QSelf, Result, Token, Type,
TypeParamBound, TypePath, Variant, Visibility, WherePredicate,
parse::{Parse, ParseBuffer, ParseStream},
parse_quote,
punctuated::Punctuated,
token,
visit_mut::{self, VisitMut},
};
pub(crate) type Variants = Punctuated<Variant, Token![,]>;
macro_rules! parse_quote_spanned {
($span:expr => $($tt:tt)*) => {
syn::parse2(quote::quote_spanned!($span => $($tt)*)).unwrap_or_else(|e| panic!("{}", e))
};
}
/// 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: &mut Generics) {
struct CollectLifetimes(Vec<String>);
impl VisitMut for CollectLifetimes {
fn visit_lifetime_param_mut(&mut self, def: &mut LifetimeParam) {
self.0.push(def.lifetime.to_string());
}
}
debug_assert!(lifetime_name.starts_with('\''));
let mut lifetimes = CollectLifetimes(vec![]);
lifetimes.visit_generics_mut(generics);
while lifetimes.0.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: Type = 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: <Token![:]>::default(),
bounds: punct,
})
}
/// Inserts a `lifetime` at position `0` of `generics.params`.
pub(crate) fn insert_lifetime(generics: &mut Generics, lifetime: Lifetime) {
generics.lt_token.get_or_insert_with(<Token![<]>::default);
generics.gt_token.get_or_insert_with(<Token![>]>::default);
generics.params.insert(0, LifetimeParam::new(lifetime).into());
}
/// Determines the visibility of the projected types and projection methods.
///
/// If given visibility is `pub`, returned visibility is `pub(crate)`.
/// Otherwise, returned visibility is the same as given visibility.
pub(crate) fn determine_visibility(vis: &Visibility) -> Visibility {
if let Visibility::Public(token) = vis {
parse_quote_spanned!(token.span => pub(crate))
} else {
vis.clone()
}
}
pub(crate) fn respan<T>(node: &T, span: Span) -> T
where
T: ToTokens + Parse,
{
let tokens = node.to_token_stream();
let respanned = respan_tokens(tokens, span);
syn::parse2(respanned).unwrap()
}
fn respan_tokens(tokens: TokenStream, span: Span) -> TokenStream {
tokens
.into_iter()
.map(|mut token| {
token.set_span(span);
token
})
.collect()
}
// -----------------------------------------------------------------------------
// extension traits
pub(crate) trait SliceExt {
fn position_exact(&self, ident: &str) -> Result<Option<usize>>;
fn find(&self, ident: &str) -> Option<&Attribute>;
}
impl SliceExt for [Attribute] {
/// # Errors
///
/// - There are multiple specified attributes.
/// - The `Attribute::tokens` field of the specified attribute is not empty.
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.replace(i).is_some() {
bail!(attr, "duplicate #[{}] attribute", ident);
}
attr.meta.require_path_only()?;
}
Ok((i + 1, prev))
})
.map(|(_, pos)| pos)
}
fn find(&self, ident: &str) -> Option<&Attribute> {
self.iter().position(|attr| attr.path().is_ident(ident)).map(|i| &self[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.35/src/receiver.rs
// - https://github.com/dtolnay/async-trait/commit/6029cbf375c562ca98fa5748e9d950a8ff93b0e7
pub(crate) struct ReplaceReceiver<'a>(pub(crate) &'a TypePath);
impl ReplaceReceiver<'_> {
fn self_ty(&self, span: Span) -> TypePath {
respan(self.0, span)
}
fn self_to_qself(&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;
}
let span = first.ident.span();
*qself = Some(QSelf {
lt_token: Token![<](span),
ty: Box::new(self.self_ty(span).into()),
position: 0,
as_token: None,
gt_token: Token![>](span),
});
path.leading_colon = Some(**path.segments.pairs().next().unwrap().punct().unwrap());
let segments = mem::take(&mut path.segments);
path.segments = segments.into_pairs().skip(1).collect();
}
fn self_to_expr_path(&self, path: &mut Path) {
if path.leading_colon.is_some() {
return;
}
let first = &path.segments[0];
if first.ident != "Self" || !first.arguments.is_empty() {
return;
}
let self_ty = self.self_ty(first.ident.span());
let variant = mem::replace(path, self_ty.path);
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![::]>::default());
}
}
}
if variant.segments.len() > 1 {
path.segments.push_punct(<Token![::]>::default());
path.segments.extend(variant.segments.into_pairs().skip(1));
}
}
fn visit_token_stream(&self, tokens: &mut TokenStream) -> bool {
let mut out = vec![];
let mut modified = false;
let mut iter = tokens.clone().into_iter().peekable();
while let Some(tt) = iter.next() {
match tt {
TokenTree::Ident(mut ident) => {
modified |= prepend_underscore_to_self(&mut ident);
if ident == "Self" {
modified = true;
let self_ty = self.self_ty(ident.span());
match iter.peek() {
Some(TokenTree::Punct(p))
if p.as_char() == ':' && p.spacing() == Spacing::Joint =>
{
let next = iter.next().unwrap();
match iter.peek() {
Some(TokenTree::Punct(p)) if p.as_char() == ':' => {
let span = ident.span();
out.extend(quote_spanned!(span=> <#self_ty>));
}
_ => out.extend(quote!(#self_ty)),
}
out.push(next);
}
_ => out.extend(quote!(#self_ty)),
}
} else {
out.push(TokenTree::Ident(ident));
}
}
TokenTree::Group(group) => {
let mut content = group.stream();
modified |= self.visit_token_stream(&mut content);
let mut new = Group::new(group.delimiter(), content);
new.set_span(group.span());
out.push(TokenTree::Group(new));
}
other => out.push(other),
}
}
if modified {
*tokens = TokenStream::from_iter(out);
}
modified
}
}
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(node.path.segments[0].ident.span()).into();
} 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() {
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) {
self.self_to_expr_path(&mut expr.path);
visit_mut::visit_expr_struct_mut(self, expr);
}
fn visit_pat_struct_mut(&mut self, pat: &mut PatStruct) {
self.self_to_expr_path(&mut pat.path);
visit_mut::visit_pat_struct_mut(self, pat);
}
fn visit_pat_tuple_struct_mut(&mut self, pat: &mut PatTupleStruct) {
self.self_to_expr_path(&mut pat.path);
visit_mut::visit_pat_tuple_struct_mut(self, pat);
}
fn visit_path_mut(&mut self, path: &mut Path) {
if path.segments.len() == 1 {
// Replace `self`, but not `self::function`.
prepend_underscore_to_self(&mut path.segments[0].ident);
}
for segment in &mut path.segments {
self.visit_path_arguments_mut(&mut segment.arguments);
}
}
fn visit_item_mut(&mut self, item: &mut Item) {
match item {
// Visit `macro_rules!` because locally defined macros can refer to `self`.
Item::Macro(item) if item.mac.path.is_ident("macro_rules") => {
self.visit_macro_mut(&mut item.mac);
}
// Otherwise, do not recurse into nested items.
_ => {}
}
}
fn visit_macro_mut(&mut self, mac: &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(mac.tokens.clone()) {
self.visit_token_stream(&mut mac.tokens);
}
}
}
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,
})
}
pub(crate) fn prepend_underscore_to_self(ident: &mut Ident) -> bool {
let modified = ident == "self";
if modified {
*ident = Ident::new("__self", ident.span());
}
modified
}