diff --git a/core/src/from_meta.rs b/core/src/from_meta.rs index ba2a3a2e..cf25e23e 100644 --- a/core/src/from_meta.rs +++ b/core/src/from_meta.rs @@ -122,7 +122,14 @@ pub trait FromMeta: Sized { fn from_expr(expr: &Expr) -> Result { match *expr { Expr::Lit(ref lit) => Self::from_value(&lit.lit), - Expr::Group(ref group) => Self::from_expr(&group.expr), + Expr::Group(ref group) => { + // syn may generate this invisible group delimiter when the input to the darling + // proc macro (specifically, the attributes) are generated by a + // macro_rules! (e.g. propagating a macro_rules!'s expr) + // Since we want to basically ignore these invisible group delimiters, + // we just propagate the call to the inner expression. + Self::from_expr(&group.expr) + } _ => Err(Error::unexpected_expr_type(expr)), } .map_err(|e| e.with_span(expr)) @@ -292,13 +299,14 @@ impl FromMeta for syn::punctuated::P /// alternate parsing modes for this type. impl FromMeta for syn::Expr { fn from_expr(expr: &Expr) -> Result { - if let syn::Expr::Lit(expr_lit) = expr { - if let syn::Lit::Str(_) = &expr_lit.lit { - return Self::from_value(&expr_lit.lit); - } + match expr { + Expr::Lit(syn::ExprLit { + lit: lit @ syn::Lit::Str(_), + .. + }) => Self::from_value(lit), + Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr + _ => Ok(expr.clone()), } - - Ok(expr.clone()) } fn from_string(value: &str) -> Result { @@ -333,6 +341,7 @@ impl FromMeta for syn::Path { match expr { Expr::Lit(lit) => Self::from_value(&lit.lit), Expr::Path(path) => Ok(path.path.clone()), + Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr _ => Err(Error::unexpected_expr_type(expr)), } } @@ -361,6 +370,7 @@ impl FromMeta for syn::Ident { Some(ident) => Ok(ident.clone()), None => Err(Error::unexpected_expr_type(expr)), }, + Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr _ => Err(Error::unexpected_expr_type(expr)), } } @@ -380,12 +390,11 @@ macro_rules! from_syn_expr_type { ($ty:path, $variant:ident) => { impl FromMeta for $ty { fn from_expr(expr: &syn::Expr) -> Result { - if let syn::Expr::$variant(body) = expr { - Ok(body.clone()) - } else if let syn::Expr::Lit(expr_lit) = expr { - Self::from_value(&expr_lit.lit) - } else { - Err(Error::unexpected_expr_type(expr)) + match expr { + syn::Expr::$variant(body) => Ok(body.clone()), + syn::Expr::Lit(expr_lit) => Self::from_value(&expr_lit.lit), + syn::Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr + _ => Err(Error::unexpected_expr_type(expr)), } } @@ -452,21 +461,27 @@ macro_rules! from_numeric_array { /// Parsing an unsigned integer array, i.e. `example = "[1, 2, 3, 4]"`. impl FromMeta for Vec<$ty> { fn from_expr(expr: &syn::Expr) -> Result { - if let syn::Expr::Array(expr_array) = expr { - let v = expr_array + match expr { + syn::Expr::Array(expr_array) => expr_array .elems .iter() - .map(|expr| match expr { - Expr::Lit(lit) => $ty::from_value(&lit.lit), - _ => Err(Error::custom("Expected array of unsigned integers") - .with_span(expr)), + .map(|expr| { + let unexpected = || { + Error::custom("Expected array of unsigned integers").with_span(expr) + }; + match expr { + Expr::Lit(lit) => $ty::from_value(&lit.lit), + Expr::Group(group) => match &*group.expr { + Expr::Lit(lit) => $ty::from_value(&lit.lit), + _ => Err(unexpected()), + }, + _ => Err(unexpected()), + } }) - .collect::>>(); - v - } else if let syn::Expr::Lit(expr_lit) = expr { - Self::from_value(&expr_lit.lit) - } else { - Err(Error::unexpected_expr_type(expr)) + .collect::>>(), + syn::Expr::Lit(expr_lit) => Self::from_value(&expr_lit.lit), + syn::Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr + _ => Err(Error::unexpected_expr_type(expr)), } }