From: Matt Corallo Date: Tue, 29 Mar 2022 22:33:27 +0000 (+0000) Subject: Crack `ReadableArgs` params when they're tuples X-Git-Tag: v0.0.106.0~2^2~1 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=f05687b6d75e35ac71f96ca84dce38664d18e5cf;p=ldk-c-bindings Crack `ReadableArgs` params when they're tuples This replaces the special handling we'd had in 0.0.105.2 for tuples-containing-references by instead just cracking open the tuples and converting each field individually when calling `ReadableArgs` where the argument is a tuple. --- diff --git a/c-bindings-gen/src/main.rs b/c-bindings-gen/src/main.rs index fbe3c99..d62b2a3 100644 --- a/c-bindings-gen/src/main.rs +++ b/c-bindings-gen/src/main.rs @@ -102,24 +102,44 @@ fn maybe_convert_trait_impl(w: &mut W, trait_path: &syn::Path let mut arg_conv = Vec::new(); if t == "lightning::util::ser::ReadableArgs" { - write!(w, ", arg: ").unwrap(); assert!(trait_path.leading_colon.is_none()); let args_seg = trait_path.segments.iter().last().unwrap(); assert_eq!(format!("{}", args_seg.ident), "ReadableArgs"); if let syn::PathArguments::AngleBracketed(args) = &args_seg.arguments { assert_eq!(args.args.len(), 1); if let syn::GenericArgument::Type(args_ty) = args.args.iter().next().unwrap() { - types.write_c_type(w, args_ty, Some(generics), false); + macro_rules! write_arg_conv { + ($ty: expr, $arg_name: expr) => { + write!(w, ", {}: ", $arg_name).unwrap(); + types.write_c_type(w, $ty, Some(generics), false); + + write!(&mut arg_conv, "\t").unwrap(); + if types.write_from_c_conversion_new_var(&mut arg_conv, &format_ident!("{}", $arg_name), &$ty, Some(generics)) { + write!(&mut arg_conv, "\n\t").unwrap(); + } - write!(&mut arg_conv, "\t").unwrap(); - if types.write_from_c_conversion_new_var(&mut arg_conv, &format_ident!("arg"), &args_ty, Some(generics)) { - write!(&mut arg_conv, "\n\t").unwrap(); + write!(&mut arg_conv, "let {}_conv = ", $arg_name).unwrap(); + types.write_from_c_conversion_prefix(&mut arg_conv, &$ty, Some(generics)); + write!(&mut arg_conv, "{}", $arg_name).unwrap(); + types.write_from_c_conversion_suffix(&mut arg_conv, &$ty, Some(generics)); + write!(&mut arg_conv, ";\n").unwrap(); + } } - write!(&mut arg_conv, "let arg_conv = ").unwrap(); - types.write_from_c_conversion_prefix(&mut arg_conv, &args_ty, Some(generics)); - write!(&mut arg_conv, "arg").unwrap(); - types.write_from_c_conversion_suffix(&mut arg_conv, &args_ty, Some(generics)); + if let syn::Type::Tuple(tup) = args_ty { + // Crack open tuples and make them separate arguments instead of + // converting the full tuple. This makes it substantially easier to + // reason about things like references in the tuple fields. + let mut arg_conv_res = Vec::new(); + for (idx, elem) in tup.elems.iter().enumerate() { + let arg_name = format!("arg_{}", ('a' as u8 + idx as u8) as char); + write_arg_conv!(elem, arg_name); + write!(&mut arg_conv_res, "{}_conv{}", arg_name, if idx != tup.elems.len() - 1 { ", " } else { "" }).unwrap(); + } + writeln!(&mut arg_conv, "\tlet arg_conv = ({});", String::from_utf8(arg_conv_res).unwrap()).unwrap(); + } else { + write_arg_conv!(args_ty, "arg"); + } } else { unreachable!(); } } else { unreachable!(); } } else if t == "lightning::util::ser::MaybeReadable" { @@ -131,7 +151,6 @@ fn maybe_convert_trait_impl(w: &mut W, trait_path: &syn::Path if t == "lightning::util::ser::ReadableArgs" { w.write(&arg_conv).unwrap(); - write!(w, ";\n").unwrap(); } write!(w, "\tlet res: ").unwrap(); diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index 28e05f8..ced1f34 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -2714,7 +2714,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if !c_ty { self.write_rust_path(w, generics, path); } else { - write!(w, "{}", full_path).unwrap(); + // We shouldn't be mapping references in types, so panic here + unimplemented!(); } } else if is_ref { write!(w, "&{}{}{}", if is_mut { "mut " } else { "" }, crate_pfx, full_path).unwrap();