From 51c723a84f66efe01c34410a5548bbac1e62f411 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 6 Oct 2021 13:22:56 -0500 Subject: [PATCH] fix(derive): Fix the problem where the build fails due to the ambiguous type of `map` > This PR closes #490. Please refer to #490 for the detail of the problem. Let me know if you want to make `convert_type` a function. This is a port of https://github.com/TeXitoi/structopt/pull/491 This is part of #2809 --- clap_derive/src/derives/args.rs | 11 +++++++++-- clap_derive/tests/issues.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/clap_derive/src/derives/args.rs b/clap_derive/src/derives/args.rs index 9e1d1ebba63..65ae34efc1f 100644 --- a/clap_derive/src/derives/args.rs +++ b/clap_derive/src/derives/args.rs @@ -542,6 +542,13 @@ fn gen_parsers( 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, + }; // Use `quote!` to give this identifier the same hygiene // as the `arg_matches` parameter definition. This // allows us to refer to `arg_matches` within a `quote_spanned` block @@ -584,7 +591,7 @@ fn gen_parsers( Ty::OptionVec => quote_spanned! { ty.span()=> if #arg_matches.is_present(#name) { Some(#arg_matches.#values_of(#name) - .map(|v| v.map(#parse).collect()) + .map(|v| v.map::<#convert_type, _>(#parse).collect()) .unwrap_or_else(Vec::new)) } else { None @@ -600,7 +607,7 @@ fn gen_parsers( quote_spanned! { ty.span()=> #arg_matches.#values_of(#name) - .map(|v| v.map(#parse).collect()) + .map(|v| v.map::<#convert_type, _>(#parse).collect()) .unwrap_or_else(Vec::new) } } diff --git a/clap_derive/tests/issues.rs b/clap_derive/tests/issues.rs index b4bd69e001f..c386bc91fc8 100644 --- a/clap_derive/tests/issues.rs +++ b/clap_derive/tests/issues.rs @@ -76,3 +76,32 @@ fn issue_324() { let help = get_long_help::(); assert!(help.contains("MY_VERSION")); } + +#[test] +fn issue_490() { + use clap::Clap; + use std::iter::FromIterator; + use std::str::FromStr; + + struct U16ish; + impl FromStr for U16ish { + type Err = (); + fn from_str(_: &str) -> Result { + unimplemented!() + } + } + impl<'a> FromIterator<&'a U16ish> for Vec { + fn from_iter>(_: T) -> Self { + unimplemented!() + } + } + + #[derive(Clap, Debug)] + struct Opt { + opt_vec: Vec, + #[clap(long)] + opt_opt_vec: Option>, + } + + // Assert that it compiles +}