diff --git a/pyo3-macros-backend/src/pyclass.rs b/pyo3-macros-backend/src/pyclass.rs index 403e5e8e9dc..7a10edbe58c 100644 --- a/pyo3-macros-backend/src/pyclass.rs +++ b/pyo3-macros-backend/src/pyclass.rs @@ -230,34 +230,58 @@ pub fn build_py_class( For an explanation, see https://pyo3.rs/latest/class.html#no-generic-parameters" ); - let mut field_options: Vec<(&syn::Field, FieldPyO3Options)> = match &mut class.fields { - syn::Fields::Named(fields) => fields - .named - .iter_mut() - .map(|field| { - FieldPyO3Options::take_pyo3_options(&mut field.attrs) - .map(move |options| (&*field, options)) - }) - .collect::>()?, - syn::Fields::Unnamed(fields) => fields - .unnamed - .iter_mut() - .map(|field| { - FieldPyO3Options::take_pyo3_options(&mut field.attrs) - .map(move |options| (&*field, options)) - }) - .collect::>()?, - syn::Fields::Unit => { - if let Some(attr) = args.options.set_all { - return Err(syn::Error::new_spanned(attr, UNIT_SET)); - }; - if let Some(attr) = args.options.get_all { - return Err(syn::Error::new_spanned(attr, UNIT_GET)); - }; - // No fields for unit struct - Vec::new() + let mut field_options_res: Vec> = + match &mut class.fields { + syn::Fields::Named(fields) => fields + .named + .iter_mut() + .map(|field| { + FieldPyO3Options::take_pyo3_options(&mut field.attrs) + .map(move |options| (&*field, options)) + }) + .collect::>(), + syn::Fields::Unnamed(fields) => fields + .unnamed + .iter_mut() + .map(|field| { + FieldPyO3Options::take_pyo3_options(&mut field.attrs) + .map(move |options| (&*field, options)) + }) + .collect::>(), + syn::Fields::Unit => { + if let Some(attr) = args.options.set_all { + return Err(syn::Error::new_spanned(attr, UNIT_SET)); + }; + if let Some(attr) = args.options.get_all { + return Err(syn::Error::new_spanned(attr, UNIT_GET)); + }; + // No fields for unit struct + Vec::new() + } + }; + + // handle error here + + let mut allerr = Vec::new(); + + let mut field_options: Vec<(&syn::Field, FieldPyO3Options)> = field_options_res + .drain(..) + .filter_map(|result| match result { + Err(err) => { + allerr.push(err.clone()); + None + } + Ok(options) => Some(options), + }) + .collect::>(); + + if !allerr.is_empty() { + let mut error = allerr[0].clone(); + for err in &allerr[1..] { + error.combine(err.clone()); } - }; + return Err(error); + } if let Some(attr) = args.options.get_all { for (_, FieldPyO3Options { get, .. }) in &mut field_options {