Upgrade rust/crates/pin-project-internal to 0.4.17

Test: None
Change-Id: I3aae35d8458fa54a79389307854e9f1bb62307ac
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 @@
     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 @@
 /// # }
 /// ```
 ///
+/// 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 @@
 ///    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 @@
 ///    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 @@
 ///
 /// [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 @@
 /// }
 ///
 /// 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 @@
 /// [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 @@
     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 @@
         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 @@
                     "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 @@
             (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 @@
     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 @@
         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 @@
             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 @@
             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 @@
         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 @@
         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 @@
         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 {