summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaibo Huang <hhb@google.com>2020-05-18 15:51:17 -0700
committerHaibo Huang <hhb@google.com>2020-05-18 15:51:17 -0700
commit75f2babc143bd234e6ae0adbc7f3e0d791338fa1 (patch)
tree00e724cbf628c61b57aef77235cf0b8056fbe3bc
parent4fc489c9173e6f5ec4587be3808b2acde3bbf067 (diff)
downloadpin-project-internal-75f2babc143bd234e6ae0adbc7f3e0d791338fa1.tar.gz
Upgrade rust/crates/pin-project-internal to 0.4.17platform-tools-30.0.3platform-tools-30.0.2
Test: None Change-Id: I3aae35d8458fa54a79389307854e9f1bb62307ac
-rw-r--r--Cargo.toml2
-rw-r--r--Cargo.toml.orig2
-rw-r--r--METADATA4
-rw-r--r--src/lib.rs54
-rw-r--r--src/pin_project/derive.rs77
5 files changed, 105 insertions, 34 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 0d2fa81..351fe27 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "pin-project-internal"
-version = "0.4.16"
+version = "0.4.17"
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"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index bbcc261..e5dce33 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "pin-project-internal"
-version = "0.4.16"
+version = "0.4.17"
authors = ["Taiki Endo <te316e89@gmail.com>"]
edition = "2018"
license = "Apache-2.0 OR MIT"
diff --git a/METADATA b/METADATA
index 7f311b3..eb7aaeb 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@ third_party {
type: GIT
value: "https://github.com/taiki-e/pin-project"
}
- version: "0.4.16"
+ version: "0.4.17"
license_type: NOTICE
last_upgrade_date {
year: 2020
month: 5
- day: 11
+ day: 18
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 0e5f976..b73888c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,7 +1,7 @@
//! 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.16")]
+#![doc(html_root_url = "https://docs.rs/pin-project-internal/0.4.17")]
#![doc(test(
no_crate_inject,
attr(deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code))
@@ -9,8 +9,8 @@
#![warn(unsafe_code)]
#![warn(rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
#![warn(clippy::all, clippy::default_trait_access)]
-// mem::take requires Rust 1.40
-#![allow(clippy::mem_replace_with_default)]
+// mem::take and #[non_exhaustive] requires Rust 1.40
+#![allow(clippy::mem_replace_with_default, clippy::manual_non_exhaustive)]
#![allow(clippy::needless_doctest_main)]
// older compilers require explicit `extern crate`.
@@ -50,6 +50,27 @@ use crate::utils::{Immutable, Mutable, Owned};
/// # }
/// ```
///
+/// By passing an argument with the same name as the method to the attribute,
+/// you can name the projection type returned from the method:
+///
+/// ```rust
+/// use pin_project::pin_project;
+/// use std::pin::Pin;
+///
+/// #[pin_project(project = EnumProj)]
+/// enum Enum<T> {
+/// Variant(#[pin] T),
+/// }
+///
+/// fn func<T>(x: Pin<&mut Enum<T>>) {
+/// match x.project() {
+/// EnumProj::Variant(y) => {
+/// let _: Pin<&mut T> = y;
+/// }
+/// }
+/// }
+/// ```
+///
/// 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 downgraded to `pub(crate)`.
@@ -67,7 +88,7 @@ use crate::utils::{Immutable, Mutable, Owned};
/// 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.
+/// [`UnsafeUnpin`][unsafe-unpin] argument.
///
/// 2. The destructor of the struct must not move structural fields out of its argument.
///
@@ -84,8 +105,8 @@ use crate::utils::{Immutable, Mutable, Owned};
/// 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]`][pinned-drop]. This function takes a pinned version of your struct -
+/// 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
@@ -184,17 +205,14 @@ use crate::utils::{Immutable, Mutable, Owned};
///
/// [Enums](https://doc.rust-lang.org/reference/items/enumerations.html):
///
-/// `#[pin_project]` 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.
+/// `#[pin_project]` supports enums, but to use it, you need to name the
+/// projection type returned from the method or to use with the [`project`] attribute.
///
/// ```rust
-/// use pin_project::{pin_project, project};
+/// use pin_project::pin_project;
/// use std::pin::Pin;
///
-/// #[pin_project]
+/// #[pin_project(project = EnumProj)]
/// enum Enum<T, U> {
/// Tuple(#[pin] T),
/// Struct { field: U },
@@ -202,17 +220,15 @@ use crate::utils::{Immutable, Mutable, Owned};
/// }
///
/// impl<T, U> Enum<T, U> {
-/// #[project] // Nightly does not need a dummy attribute to the function.
/// fn method(self: Pin<&mut Self>) {
-/// #[project]
/// match self.project() {
-/// Enum::Tuple(x) => {
+/// EnumProj::Tuple(x) => {
/// let _: Pin<&mut T> = x;
/// }
-/// Enum::Struct { field } => {
+/// EnumProj::Struct { field } => {
/// let _: &mut U = field;
/// }
-/// Enum::Unit => {}
+/// EnumProj::Unit => {}
/// }
/// }
/// }
@@ -410,7 +426,7 @@ use crate::utils::{Immutable, Mutable, Owned};
/// [repr-packed]: https://doc.rust-lang.org/nomicon/other-reprs.html#reprpacked
/// [pin-projection]: https://doc.rust-lang.org/nightly/std/pin/index.html#projections-and-structural-pinning
/// [undefined-behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
-/// [unsafe-unpin]: ./attr.pin_project.html#pinned_drop
+/// [unsafe-unpin]: ./attr.pin_project.html#unsafeunpin
#[proc_macro_attribute]
pub fn pin_project(args: TokenStream, input: TokenStream) -> TokenStream {
pin_project::attribute(&args.into(), input.into()).into()
diff --git a/src/pin_project/derive.rs b/src/pin_project/derive.rs
index f804022..25e9623 100644
--- a/src/pin_project/derive.rs
+++ b/src/pin_project/derive.rs
@@ -110,6 +110,12 @@ struct Args {
replace: Option<Span>,
/// `UnsafeUnpin` or `!Unpin` argument.
unpin_impl: UnpinImpl,
+ /// `project = <ident>`.
+ project: Option<Ident>,
+ /// `project_ref = <ident>`.
+ project_ref: Option<Ident>,
+ /// `project_replace = <ident>`.
+ project_replace: Option<Ident>,
}
const DUPLICATE_PIN: &str = "duplicate #[pin] attribute";
@@ -187,6 +193,9 @@ impl Parse for Args {
let mut replace = None;
let mut unsafe_unpin = None;
let mut not_unpin = None;
+ let mut project = None;
+ let mut project_ref = None;
+ let mut project_replace: Option<(Span, Ident)> = None;
while !input.is_empty() {
if input.peek(token::Bang) {
let t: token::Bang = input.parse()?;
@@ -201,6 +210,18 @@ impl Parse for Args {
"PinnedDrop" => update(&mut pinned_drop, token.span(), &token)?,
"Replace" => update(&mut replace, token.span(), &token)?,
"UnsafeUnpin" => update(&mut unsafe_unpin, token.span(), &token)?,
+ "project" => {
+ let _: token::Eq = input.parse()?;
+ update(&mut project, input.parse()?, &token)?;
+ }
+ "project_ref" => {
+ let _: token::Eq = input.parse()?;
+ update(&mut project_ref, input.parse()?, &token)?;
+ }
+ "project_replace" => {
+ let _: token::Eq = input.parse()?;
+ update(&mut project_replace, (token.span(), input.parse()?), &token)?;
+ }
_ => return Err(error!(token, "unexpected argument: {}", token)),
}
}
@@ -228,7 +249,21 @@ impl Parse for Args {
(None, Some(span)) => UnpinImpl::Negative(span.span),
};
- Ok(Self { pinned_drop, replace, unpin_impl })
+ if let (Some((span, _)), None) = (&project_replace, replace) {
+ Err(Error::new(
+ *span,
+ "`project_replace` argument can only be used together with `Replace` argument",
+ ))
+ } else {
+ Ok(Self {
+ pinned_drop,
+ replace,
+ unpin_impl,
+ project,
+ project_ref,
+ project_replace: project_replace.map(|(_, i)| i),
+ })
+ }
}
}
@@ -294,6 +329,12 @@ struct Context<'a> {
replace: Option<Span>,
/// `UnsafeUnpin` or `!Unpin` argument.
unpin_impl: UnpinImpl,
+ /// `project` argument.
+ project: bool,
+ /// `project_ref` argument.
+ project_ref: bool,
+ /// `project_replace` argument.
+ project_replace: bool,
}
#[derive(Clone, Copy)]
@@ -312,7 +353,8 @@ impl<'a> Context<'a> {
ident: &'a Ident,
generics: &'a mut Generics,
) -> Result<Self> {
- let Args { pinned_drop, replace, unpin_impl } = Args::get(attrs)?;
+ let Args { pinned_drop, unpin_impl, replace, project, project_ref, project_replace } =
+ Args::get(attrs)?;
let ty_generics = generics.split_for_impl().1;
let self_ty = syn::parse_quote!(#ident #ty_generics);
@@ -339,11 +381,14 @@ impl<'a> Context<'a> {
pinned_drop,
replace,
unpin_impl,
+ project: project.is_some(),
+ project_ref: project_ref.is_some(),
+ project_replace: project_replace.is_some(),
proj: ProjectedType {
vis: determine_visibility(vis),
- mut_ident: Mutable.proj_ident(ident),
- ref_ident: Immutable.proj_ident(ident),
- own_ident: Owned.proj_ident(ident),
+ mut_ident: project.unwrap_or_else(|| Mutable.proj_ident(ident)),
+ ref_ident: project_ref.unwrap_or_else(|| Immutable.proj_ident(ident)),
+ own_ident: project_replace.unwrap_or_else(|| Owned.proj_ident(ident)),
lifetime,
generics: proj_generics,
where_clause,
@@ -398,13 +443,18 @@ impl<'a> Context<'a> {
Fields::Unit => unreachable!(),
};
+ // If the user gave it a name, it should appear in the document.
+ let doc_attr = quote!(#[doc(hidden)]);
+ let doc_proj = if self.project { None } else { Some(&doc_attr) };
+ let doc_proj_ref = if self.project_ref { None } else { Some(&doc_attr) };
+ let doc_proj_own = if self.project_replace { None } else { Some(&doc_attr) };
let mut proj_items = quote! {
- #[doc(hidden)] // TODO: If the user gave it a name, it should appear in the document.
+ #doc_proj
#[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
#[allow(dead_code)] // This lint warns unused fields/variants.
#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
#vis struct #proj_ident #proj_generics #where_clause_fields
- #[doc(hidden)] // TODO: If the user gave it a name, it should appear in the document.
+ #doc_proj_ref
#[allow(dead_code)] // This lint warns unused fields/variants.
#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
#vis struct #proj_ref_ident #proj_generics #where_clause_ref_fields
@@ -412,7 +462,7 @@ impl<'a> Context<'a> {
if self.replace.is_some() {
// Currently, using quote_spanned here does not seem to have any effect on the diagnostics.
proj_items.extend(quote! {
- #[doc(hidden)] // TODO: If the user gave it a name, it should appear in the document.
+ #doc_proj_own
#[allow(dead_code)] // This lint warns unused fields/variants.
#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
#vis struct #proj_own_ident #orig_generics #where_clause_own_fields
@@ -482,15 +532,20 @@ impl<'a> Context<'a> {
let proj_generics = &self.proj.generics;
let where_clause = &self.proj.where_clause;
+ // If the user gave it a name, it should appear in the document.
+ let doc_attr = quote!(#[doc(hidden)]);
+ let doc_proj = if self.project { None } else { Some(&doc_attr) };
+ let doc_proj_ref = if self.project_ref { None } else { Some(&doc_attr) };
+ let doc_proj_own = if self.project_replace { None } else { Some(&doc_attr) };
let mut proj_items = quote! {
- #[doc(hidden)] // TODO: If the user gave it a name, it should appear in the document.
+ #doc_proj
#[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
#[allow(dead_code)] // This lint warns unused fields/variants.
#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
#vis enum #proj_ident #proj_generics #where_clause {
#proj_variants
}
- #[doc(hidden)] // TODO: If the user gave it a name, it should appear in the document.
+ #doc_proj_ref
#[allow(dead_code)] // This lint warns unused fields/variants.
#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
#vis enum #proj_ref_ident #proj_generics #where_clause {
@@ -500,7 +555,7 @@ impl<'a> Context<'a> {
if self.replace.is_some() {
// Currently, using quote_spanned here does not seem to have any effect on the diagnostics.
proj_items.extend(quote! {
- #[doc(hidden)] // TODO: If the user gave it a name, it should appear in the document.
+ #doc_proj_own
#[allow(dead_code)] // This lint warns unused fields/variants.
#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
#vis enum #proj_own_ident #orig_generics #orig_where_clause {