Merge "Upgrade rust/crates/structopt-derive to 0.4.16"
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 887fa2d..0057313 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
 {
   "git": {
-    "sha1": "004cfc218e7fbfdbecc4088f9e3fa5061f36cb4d"
+    "sha1": "88e5402df017c052f1524f293b2e13bd01810819"
   }
 }
diff --git a/Android.bp b/Android.bp
index eec57d9..cd2b353 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,4 @@
-// This file is generated by cargo2android.py --run --tests --dependencies.
+// This file is generated by cargo2android.py --run --tests.
 // Do not modify this file as changes will be overridden on upgrade.
 
 package {
@@ -42,6 +42,8 @@
 rust_proc_macro {
     name: "libstructopt_derive",
     crate_name: "structopt_derive",
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.4.16",
     srcs: ["src/lib.rs"],
     edition: "2018",
     rustlibs: [
@@ -56,6 +58,8 @@
 rust_test_host {
     name: "structopt-derive_host_test_src_lib",
     crate_name: "structopt_derive",
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.4.16",
     srcs: ["src/lib.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
@@ -71,14 +75,3 @@
         "libsyn",
     ],
 }
-
-// dependent_library ["feature_list"]
-//   heck-0.3.3
-//   proc-macro-error-1.0.4 "default,syn,syn-error"
-//   proc-macro-error-attr-1.0.4
-//   proc-macro2-1.0.28 "default,proc-macro"
-//   quote-1.0.9 "default,proc-macro"
-//   syn-1.0.74 "clone-impls,default,derive,full,parsing,printing,proc-macro,quote"
-//   unicode-segmentation-1.8.0
-//   unicode-xid-0.2.2 "default"
-//   version_check-0.9.3
diff --git a/Cargo.toml b/Cargo.toml
index 6a9c2b1..7a10314 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "structopt-derive"
-version = "0.4.15"
+version = "0.4.16"
 authors = ["Guillaume Pinot <texitoi@texitoi.eu>"]
 description = "Parse command line argument by defining a struct, derive crate."
 documentation = "https://docs.rs/structopt-derive"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index db7e295..b41ac8a 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "structopt-derive"
-version = "0.4.15"
+version = "0.4.16"
 edition = "2018"
 authors = ["Guillaume Pinot <texitoi@texitoi.eu>"]
 description = "Parse command line argument by defining a struct, derive crate."
diff --git a/METADATA b/METADATA
index e5e5980..6f27d42 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/structopt-derive/structopt-derive-0.4.15.crate"
+    value: "https://static.crates.io/crates/structopt-derive/structopt-derive-0.4.16.crate"
   }
-  version: "0.4.15"
+  version: "0.4.16"
   license_type: NOTICE
   last_upgrade_date {
     year: 2021
-    month: 8
-    day: 9
+    month: 9
+    day: 22
   }
 }
diff --git a/src/attrs.rs b/src/attrs.rs
index aa16145..35acd5a 100644
--- a/src/attrs.rs
+++ b/src/attrs.rs
@@ -405,6 +405,7 @@
         parent_attrs: Option<&Attrs>,
         argument_casing: Sp<CasingStyle>,
         env_casing: Sp<CasingStyle>,
+        allow_skip: bool,
     ) -> Self {
         let mut res = Self::new(span, name, parent_attrs, None, argument_casing, env_casing);
         res.push_attrs(attrs);
@@ -418,8 +419,10 @@
         }
         match &*res.kind {
             Kind::Subcommand(_) => abort!(res.kind.span(), "subcommand is only allowed on fields"),
-            Kind::Skip(_) => abort!(res.kind.span(), "skip is only allowed on fields"),
-            Kind::Arg(_) | Kind::ExternalSubcommand | Kind::Flatten => res,
+            Kind::Skip(_) if !allow_skip => {
+                abort!(res.kind.span(), "skip is only allowed on fields")
+            }
+            Kind::Arg(_) | Kind::ExternalSubcommand | Kind::Flatten | Kind::Skip(_) => res,
         }
     }
 
diff --git a/src/lib.rs b/src/lib.rs
index cf4dbba..b2835b4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -330,6 +330,13 @@
                 let flag = *attrs.parser().kind == ParserKind::FromFlag;
                 let occurrences = *attrs.parser().kind == ParserKind::FromOccurrences;
                 let name = attrs.cased_name();
+                let convert_type = match **ty {
+                    Ty::Vec | Ty::Option => sub_type(&field.ty).unwrap_or(&field.ty),
+                    Ty::OptionOption | Ty::OptionVec => {
+                        sub_type(&field.ty).and_then(sub_type).unwrap_or(&field.ty)
+                    }
+                    _ => &field.ty,
+                };
                 let field_value = match **ty {
                     Ty::Bool => quote_spanned!(ty.span()=> #matches.is_present(#name)),
 
@@ -349,7 +356,7 @@
                     Ty::OptionVec => quote_spanned! { ty.span()=>
                         if #matches.is_present(#name) {
                             Some(#matches.#values_of(#name)
-                                 .map_or_else(Vec::new, |v| v.map(#parse).collect()))
+                                 .map_or_else(Vec::new, |v| v.map::<#convert_type, _>(#parse).collect()))
                         } else {
                             None
                         }
@@ -357,7 +364,7 @@
 
                     Ty::Vec => quote_spanned! { ty.span()=>
                         #matches.#values_of(#name)
-                            .map_or_else(Vec::new, |v| v.map(#parse).collect())
+                            .map_or_else(Vec::new, |v| v.map::<#convert_type, _>(#parse).collect())
                     },
 
                     Ty::Other if occurrences => quote_spanned! { ty.span()=>
@@ -409,6 +416,7 @@
         None,
         Sp::call_site(DEFAULT_CASING),
         Sp::call_site(DEFAULT_ENV_CASING),
+        false,
     );
     let tokens = {
         let name = attrs.cased_name();
@@ -471,7 +479,7 @@
 ) -> TokenStream {
     use syn::Fields::*;
 
-    let subcommands = variants.iter().map(|variant| {
+    let subcommands = variants.iter().filter_map(|variant| {
         let attrs = Attrs::from_struct(
             variant.span(),
             &variant.attrs,
@@ -479,26 +487,29 @@
             Some(parent_attribute),
             parent_attribute.casing(),
             parent_attribute.env_casing(),
+            true,
         );
 
         let kind = attrs.kind();
         match &*kind {
+            Kind::Skip(_) => None,
+
             Kind::ExternalSubcommand => {
                 let app_var = Ident::new("app", Span::call_site());
-                quote_spanned! { attrs.kind().span()=>
+                Some(quote_spanned! { attrs.kind().span()=>
                     let #app_var = #app_var.setting(
                         ::structopt::clap::AppSettings::AllowExternalSubcommands
                     );
-                }
+                })
             },
 
             Kind::Flatten => {
                 match variant.fields {
                     Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
                         let ty = &unnamed[0];
-                        quote! {
+                        Some(quote! {
                             let app = <#ty as ::structopt::StructOptInternal>::augment_clap(app);
-                        }
+                        })
                     },
                     _ => abort!(
                         variant,
@@ -535,13 +546,13 @@
                 let name = attrs.cased_name();
                 let from_attrs = attrs.top_level_methods();
                 let version = attrs.version();
-                quote! {
+                Some(quote! {
                     let app = app.subcommand({
                         let #app_var = ::structopt::clap::SubCommand::with_name(#name);
                         let #app_var = #arg_block;
                         #app_var#from_attrs#version
                     });
-                }
+                })
             },
         }
     });
@@ -588,58 +599,61 @@
                 Some(parent_attribute),
                 parent_attribute.casing(),
                 parent_attribute.env_casing(),
+                true,
             );
 
             let variant_name = &variant.ident;
 
-            if let Kind::ExternalSubcommand = *attrs.kind() {
-                if ext_subcmd.is_some() {
-                    abort!(
-                        attrs.kind().span(),
-                        "Only one variant can be marked with `external_subcommand`, \
+            match *attrs.kind() {
+                Kind::ExternalSubcommand => {
+                    if ext_subcmd.is_some() {
+                        abort!(
+                            attrs.kind().span(),
+                            "Only one variant can be marked with `external_subcommand`, \
                          this is the second"
-                    );
-                }
-
-                let ty = match variant.fields {
-                    Unnamed(ref fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty,
-
-                    _ => abort!(
-                        variant,
-                        "The enum variant marked with `external_attribute` must be \
-                         a single-typed tuple, and the type must be either `Vec<String>` \
-                         or `Vec<OsString>`."
-                    ),
-                };
-
-                let (span, str_ty, values_of) = match subty_if_name(ty, "Vec") {
-                    Some(subty) => {
-                        if is_simple_ty(subty, "String") {
-                            (
-                                subty.span(),
-                                quote!(::std::string::String),
-                                quote!(values_of),
-                            )
-                        } else {
-                            (
-                                subty.span(),
-                                quote!(::std::ffi::OsString),
-                                quote!(values_of_os),
-                            )
-                        }
+                        );
                     }
 
-                    None => abort!(
-                        ty,
-                        "The type must be either `Vec<String>` or `Vec<OsString>` \
-                         to be used with `external_subcommand`."
-                    ),
-                };
+                    let ty = match variant.fields {
+                        Unnamed(ref fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty,
 
-                ext_subcmd = Some((span, variant_name, str_ty, values_of));
-                None
-            } else {
-                Some((variant, attrs))
+                        _ => abort!(
+                            variant,
+                            "The enum variant marked with `external_attribute` must be \
+                         a single-typed tuple, and the type must be either `Vec<String>` \
+                         or `Vec<OsString>`."
+                        ),
+                    };
+
+                    let (span, str_ty, values_of) = match subty_if_name(ty, "Vec") {
+                        Some(subty) => {
+                            if is_simple_ty(subty, "String") {
+                                (
+                                    subty.span(),
+                                    quote!(::std::string::String),
+                                    quote!(values_of),
+                                )
+                            } else {
+                                (
+                                    subty.span(),
+                                    quote!(::std::ffi::OsString),
+                                    quote!(values_of_os),
+                                )
+                            }
+                        }
+
+                        None => abort!(
+                            ty,
+                            "The type must be either `Vec<String>` or `Vec<OsString>` \
+                         to be used with `external_subcommand`."
+                        ),
+                    };
+
+                    ext_subcmd = Some((span, variant_name, str_ty, values_of));
+                    None
+                }
+                Kind::Skip(_) => None,
+                _ => Some((variant, attrs)),
             }
         })
         .partition(|(_, attrs)| match &*attrs.kind() {
@@ -736,7 +750,12 @@
 }
 
 #[cfg(feature = "paw")]
-fn gen_paw_impl(impl_generics: &ImplGenerics, name: &Ident, ty_generics: &TypeGenerics, where_clause: &TokenStream) -> TokenStream {
+fn gen_paw_impl(
+    impl_generics: &ImplGenerics,
+    name: &Ident,
+    ty_generics: &TypeGenerics,
+    where_clause: &TokenStream,
+) -> TokenStream {
     quote! {
         impl #impl_generics ::structopt::paw::ParseArgs for #name #ty_generics #where_clause {
             type Error = std::io::Error;
@@ -752,8 +771,10 @@
     TokenStream::new()
 }
 
-fn split_structopt_generics_for_impl(generics: &Generics) -> (ImplGenerics, TypeGenerics, TokenStream) {
-    use syn::{ token::Add, TypeParamBound::Trait };
+fn split_structopt_generics_for_impl(
+    generics: &Generics,
+) -> (ImplGenerics, TypeGenerics, TokenStream) {
+    use syn::{token::Add, TypeParamBound::Trait};
 
     fn path_ends_with(path: &Path, ident: &str) -> bool {
         path.segments.last().unwrap().ident == ident
@@ -770,7 +791,7 @@
         return false;
     }
 
-    struct TraitBoundAmendments{
+    struct TraitBoundAmendments {
         tokens: TokenStream,
         need_where: bool,
         need_comma: bool,
@@ -779,7 +800,7 @@
     impl TraitBoundAmendments {
         fn new(where_clause: Option<&WhereClause>) -> Self {
             let tokens = TokenStream::new();
-            let (need_where,need_comma) = if let Some(where_clause) = where_clause {
+            let (need_where, need_comma) = if let Some(where_clause) = where_clause {
                 if where_clause.predicates.trailing_punct() {
                     (false, false)
                 } else {
@@ -788,16 +809,20 @@
             } else {
                 (true, false)
             };
-            Self{tokens, need_where, need_comma}
+            Self {
+                tokens,
+                need_where,
+                need_comma,
+            }
         }
 
         fn add(&mut self, amendment: TokenStream) {
             if self.need_where {
-                self.tokens.extend(quote!{ where });
+                self.tokens.extend(quote! { where });
                 self.need_where = false;
             }
             if self.need_comma {
-                self.tokens.extend(quote!{ , });
+                self.tokens.extend(quote! { , });
             }
             self.tokens.extend(amendment);
             self.need_comma = true;
@@ -814,7 +839,8 @@
         if let GenericParam::Type(param) = param {
             let param_ident = &param.ident;
             if type_param_bounds_contains(&param.bounds, "StructOpt") {
-                trait_bound_amendments.add(quote!{ #param_ident : ::structopt::StructOptInternal });
+                trait_bound_amendments
+                    .add(quote! { #param_ident : ::structopt::StructOptInternal });
             }
         }
     }
@@ -824,7 +850,8 @@
             if let WherePredicate::Type(predicate) = predicate {
                 let predicate_bounded_ty = &predicate.bounded_ty;
                 if type_param_bounds_contains(&predicate.bounds, "StructOpt") {
-                    trait_bound_amendments.add(quote!{ #predicate_bounded_ty : ::structopt::StructOptInternal });
+                    trait_bound_amendments
+                        .add(quote! { #predicate_bounded_ty : ::structopt::StructOptInternal });
                 }
             }
         }
@@ -834,7 +861,7 @@
 
     let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
 
-    let where_clause = quote!{ #where_clause #trait_bound_amendments };
+    let where_clause = quote! { #where_clause #trait_bound_amendments };
 
     (impl_generics, ty_generics, where_clause)
 }
@@ -902,7 +929,6 @@
     attrs: &[Attribute],
     generics: &Generics,
 ) -> TokenStream {
-
     let (impl_generics, ty_generics, where_clause) = split_structopt_generics_for_impl(&generics);
 
     let basic_clap_app_gen = gen_clap_enum(attrs);
@@ -980,7 +1006,9 @@
             fields: syn::Fields::Named(ref fields),
             ..
         }) => impl_structopt_for_struct(struct_name, &fields.named, &input.attrs, &input.generics),
-        Enum(ref e) => impl_structopt_for_enum(struct_name, &e.variants, &input.attrs, &input.generics),
+        Enum(ref e) => {
+            impl_structopt_for_enum(struct_name, &e.variants, &input.attrs, &input.generics)
+        }
         _ => abort_call_site!("structopt only supports non-tuple structs and enums"),
     }
 }