From 95773505e4e818ea6dc6203c5ef81aa6c3db8b68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Sch=C3=A4fer?= Date: Fri, 24 Jan 2025 18:22:16 +0100 Subject: [PATCH] xso-proc: improve error message on type mismatch for extracted fields The case this affects is a field like: ``` struct Foo { #[xml(extract(fields(text(type_ = String)), namespace = .., name = ..))] foo: ServiceType, } ``` Before, we get this: ``` error[E0631]: type mismatch in closure arguments --> muchopper/libmuchopper/src/xmpp/sjn_api.rs:188:10 | 188 | #[derive(AsXml)] | ^^^^^ | | | expected due to this | found signature defined here | = note: expected closure signature `fn(&ServiceType) -> _` found closure signature `fn(&'xso_proc_as_xml_iter_lifetime std::string::String) -> _` note: required by a bound in `std::option::Option::::map` --> /home/jssfr/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:1102:12 | 1100 | pub fn map(self, f: F) -> Option | --- required by a bound in this associated function 1101 | where 1102 | F: FnOnce(T) -> U, | ^^^^^^^^^^^^^^ required by this bound in `Option::::map` = note: this error originates in the derive macro `AsXml` (in Nightly builds, run with -Z macro-backtrace for more info) ``` Afterwards, this: ``` error[E0308]: mismatched types --> muchopper/libmuchopper/src/xmpp/sjn_api.rs:207:20 | 206 | #[xml(extract(namespace = ECS, name = "service-type", fields(text(type_ = String))))] | ------ expected due to this 207 | pub service_type: ServiceType, | ^^^^^^^^^^^ expected `Option<&String>`, found `Option<&ServiceType>` | = note: expected enum `std::option::Option<&'xso_proc_as_xml_iter_lifetime std::string::String>` found enum `std::option::Option<&ServiceType>` ``` skip-changelog, because this affects a feature which already has an "Added" line in the changelog. --- xso-proc/src/field/child.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/xso-proc/src/field/child.rs b/xso-proc/src/field/child.rs index c64792902a9035e4d56cfafa1535b30186617686..82681a73f4272001b3cc38078f16355db793d24e 100644 --- a/xso-proc/src/field/child.rs +++ b/xso-proc/src/field/child.rs @@ -460,14 +460,22 @@ impl ExtractDef { // about that in [`make_from_xml_builder_parts`] implementation // corresponding to this code above, and we will not repeat it // here. + + // These sections with quote_spanned are used to improve error + // messages on type mismatches. Without these, the rustc errors + // will point at `#[derive(AsXml)]` only, instead of directly + // pointing at the sources of those types. let cast = quote_spanned! { input_ty.span()=> ::core::option::Option::from(#bound_name) }; + let type_assert = quote_spanned! { inner_ty.span()=> + ::core::option::Option<#inner_ty> + }; ( quote! { - ::xso::asxml::OptionAsXml::new(#cast.map(|#bound_name: #inner_ty| { + ::xso::asxml::OptionAsXml::new({ let x: #type_assert = #cast; x.map(|#bound_name: #inner_ty| { #item_iter_ty_ident::new((#repack)) - }).transpose()?) + })}.transpose()?) }, option_as_xml_ty(item_iter_ty), )