Skip to content

Commit 1ec49fa

Browse files
committed
Support trait impls on enums
Previously we'd only generate correct code for trait impls on structs, but there's no reason for that restriction. Here we also implement it on enums.
1 parent f8cb96c commit 1ec49fa

File tree

1 file changed

+32
-8
lines changed

1 file changed

+32
-8
lines changed

c-bindings-gen/src/main.rs

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,15 @@ fn maybe_convert_trait_impl<W: std::io::Write>(w: &mut W, trait_path: &syn::Path
9494
writeln!(w, ")").unwrap();
9595

9696
writeln!(w, "}}").unwrap();
97+
98+
writeln!(w, "#[allow(unused)]").unwrap();
99+
writeln!(w, "pub(crate) extern \"C\" fn {}_write_void(obj: *const c_void) -> crate::c_types::derived::CVec_u8Z {{", for_obj).unwrap();
97100
if has_inner {
98-
writeln!(w, "pub(crate) extern \"C\" fn {}_write_void(obj: *const c_void) -> crate::c_types::derived::CVec_u8Z {{", for_obj).unwrap();
99101
writeln!(w, "\tcrate::c_types::serialize_obj(unsafe {{ &*(obj as *const native{}) }})", for_obj).unwrap();
100-
writeln!(w, "}}").unwrap();
102+
} else {
103+
writeln!(w, "\t{}_write(unsafe {{ &*(obj as *const {}) }})", for_obj, for_obj).unwrap();
101104
}
105+
writeln!(w, "}}").unwrap();
102106
},
103107
"lightning::util::ser::Readable"|"lightning::util::ser::ReadableArgs"|"lightning::util::ser::MaybeReadable" => {
104108
// Create the Result<Object, DecodeError> syn::Type
@@ -553,6 +557,7 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty
553557
writeln!(w, "unsafe impl Send for {} {{}}", trait_name).unwrap();
554558
writeln!(w, "unsafe impl Sync for {} {{}}", trait_name).unwrap();
555559

560+
writeln!(w, "#[allow(unused)]").unwrap();
556561
writeln!(w, "pub(crate) fn {}_clone_fields(orig: &{}) -> {} {{", trait_name, trait_name, trait_name).unwrap();
557562
writeln!(w, "\t{} {{", trait_name).unwrap();
558563
writeln!(w, "\t\tthis_arg: orig.this_arg,").unwrap();
@@ -1022,10 +1027,14 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, w_uses: &mut HashSet<String, NonRa
10221027
if is_type_unconstructable(&resolved_path) {
10231028
writeln!(w, "\t\tunreachable!();").unwrap();
10241029
} else {
1025-
writeln!(w, "\t\tlet mut rust_obj = {} {{ inner: ObjOps::heap_alloc(obj), is_owned: true }};", ident).unwrap();
1026-
writeln!(w, "\t\tlet mut ret = {}_as_{}(&rust_obj);", ident, trait_obj.ident).unwrap();
1027-
writeln!(w, "\t\t// We want to free rust_obj when ret gets drop()'d, not rust_obj, so wipe rust_obj's pointer and set ret's free() fn").unwrap();
1028-
writeln!(w, "\t\trust_obj.inner = core::ptr::null_mut();").unwrap();
1030+
types.write_to_c_conversion_new_var(w, &format_ident!("obj"), &*i.self_ty, Some(&gen_types), false);
1031+
write!(w, "\t\tlet rust_obj = ").unwrap();
1032+
types.write_to_c_conversion_inline_prefix(w, &*i.self_ty, Some(&gen_types), false);
1033+
write!(w, "obj").unwrap();
1034+
types.write_to_c_conversion_inline_suffix(w, &*i.self_ty, Some(&gen_types), false);
1035+
writeln!(w, ";\n\t\tlet mut ret = {}_as_{}(&rust_obj);", ident, trait_obj.ident).unwrap();
1036+
writeln!(w, "\t\t// We want to free rust_obj when ret gets drop()'d, not rust_obj, so forget it and set ret's free() fn").unwrap();
1037+
writeln!(w, "\t\tcore::mem::forget(rust_obj);").unwrap();
10291038
writeln!(w, "\t\tret.free = Some({}_free_void);", ident).unwrap();
10301039
writeln!(w, "\t\tret").unwrap();
10311040
}
@@ -1040,7 +1049,11 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, w_uses: &mut HashSet<String, NonRa
10401049
writeln!(w, "/// This copies the `inner` pointer in this_arg and thus the returned {} must be freed before this_arg is", trait_obj.ident).unwrap();
10411050
write!(w, "#[no_mangle]\npub extern \"C\" fn {}_as_{}(this_arg: &{}) -> crate::{} {{\n", ident, trait_obj.ident, ident, full_trait_path).unwrap();
10421051
writeln!(w, "\tcrate::{} {{", full_trait_path).unwrap();
1043-
writeln!(w, "\t\tthis_arg: unsafe {{ ObjOps::untweak_ptr((*this_arg).inner) as *mut c_void }},").unwrap();
1052+
if types.c_type_has_inner_from_path(&resolved_path) {
1053+
writeln!(w, "\t\tthis_arg: unsafe {{ ObjOps::untweak_ptr((*this_arg).inner) as *mut c_void }},").unwrap();
1054+
} else {
1055+
writeln!(w, "\t\tthis_arg: unsafe {{ ObjOps::untweak_ptr(this_arg as *const {} as *mut {}) as *mut c_void }},", ident, ident).unwrap();
1056+
}
10441057
writeln!(w, "\t\tfree: None,").unwrap();
10451058

10461059
macro_rules! write_meth {
@@ -1344,7 +1357,7 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, w_uses: &mut HashSet<String, NonRa
13441357
writeln!(w, "#[allow(unused)]").unwrap();
13451358
writeln!(w, "/// Used only if an object of this type is returned as a trait impl by a method").unwrap();
13461359
writeln!(w, "pub(crate) extern \"C\" fn {}_clone_void(this_ptr: *const c_void) -> *mut c_void {{", ident).unwrap();
1347-
writeln!(w, "\tBox::into_raw(Box::new(unsafe {{ (*(this_ptr as *mut native{})).clone() }})) as *mut c_void", ident).unwrap();
1360+
writeln!(w, "\tBox::into_raw(Box::new(unsafe {{ (*(this_ptr as *const native{})).clone() }})) as *mut c_void", ident).unwrap();
13481361
writeln!(w, "}}").unwrap();
13491362
writeln!(w, "#[no_mangle]").unwrap();
13501363
writeln!(w, "/// Creates a copy of the {}", ident).unwrap();
@@ -1935,7 +1948,18 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type
19351948
writeln!(w, "pub extern \"C\" fn {}_clone(orig: &{}) -> {} {{", e.ident, e.ident, e.ident).unwrap();
19361949
writeln!(w, "\torig.clone()").unwrap();
19371950
writeln!(w, "}}").unwrap();
1951+
writeln!(w, "#[allow(unused)]").unwrap();
1952+
writeln!(w, "/// Used only if an object of this type is returned as a trait impl by a method").unwrap();
1953+
writeln!(w, "pub(crate) extern \"C\" fn {}_clone_void(this_ptr: *const c_void) -> *mut c_void {{", e.ident).unwrap();
1954+
writeln!(w, "\tBox::into_raw(Box::new(unsafe {{ (*(this_ptr as *const {})).clone() }})) as *mut c_void", e.ident).unwrap();
1955+
writeln!(w, "}}").unwrap();
19381956
}
1957+
1958+
writeln!(w, "#[allow(unused)]").unwrap();
1959+
writeln!(w, "/// Used only if an object of this type is returned as a trait impl by a method").unwrap();
1960+
writeln!(w, "pub(crate) extern \"C\" fn {}_free_void(this_ptr: *mut c_void) {{", e.ident).unwrap();
1961+
writeln!(w, "\tlet _ = unsafe {{ Box::from_raw(this_ptr as *mut {}) }};\n}}", e.ident).unwrap();
1962+
19391963
w.write_all(&constr).unwrap();
19401964
write_cpp_wrapper(cpp_headers, &format!("{}", e.ident), needs_free, None);
19411965
}

0 commit comments

Comments
 (0)