[bindings] Keep track of all types which derive[Clone]
[rust-lightning] / c-bindings-gen / src / types.rs
index 770dcb47a7807515c6adf43453e7ad8ef6474282..22f1d9e5a8596fbbffd9728ecd88d0d5fa86f6ac 100644 (file)
@@ -1,4 +1,4 @@
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
 use std::fs::File;
 use std::io::Write;
 use std::hash;
@@ -39,6 +39,30 @@ pub fn single_ident_generic_path_to_ident(p: &syn::Path) -> Option<&syn::Ident>
        } else { None }
 }
 
+pub fn attrs_derives_clone(attrs: &[syn::Attribute]) -> bool {
+       for attr in attrs.iter() {
+               let tokens_clone = attr.tokens.clone();
+               let mut token_iter = tokens_clone.into_iter();
+               if let Some(token) = token_iter.next() {
+                       match token {
+                               TokenTree::Group(g) => {
+                                       if format!("{}", single_ident_generic_path_to_ident(&attr.path).unwrap()) == "derive" {
+                                               for id in g.stream().into_iter() {
+                                                       if let TokenTree::Ident(i) = id {
+                                                               if i == "Clone" {
+                                                                       return true;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               },
+                               _ => {},
+                       }
+               }
+       }
+       false
+}
+
 #[derive(Debug, PartialEq)]
 pub enum ExportStatus {
        Export,
@@ -293,6 +317,8 @@ pub struct CrateTypes<'a> {
        /// The output file for any created template container types, written to as we find new
        /// template containers which need to be defined.
        pub template_file: &'a mut File,
+       /// Set of containers which are clonable
+       pub clonable_types: HashSet<String>,
 }
 
 /// A struct which tracks resolving rust types into C-mapped equivalents, exists for one specific
@@ -368,6 +394,16 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        _ => false,
                }
        }
+       pub fn is_clonable(&self, ty: &str) -> bool {
+               if self.crate_types.clonable_types.contains(ty) { return true; }
+               if self.is_primitive(ty) { return true; }
+               match ty {
+                       "()" => true,
+                       "crate::c_types::Signature" => true,
+                       "crate::c_types::TxOut" => true,
+                       _ => false,
+               }
+       }
        /// Gets the C-mapped type for types which are outside of the crate, or which are manually
        /// ignored by for some reason need mapping anyway.
        fn c_type_from_path<'b>(&self, full_path: &'b str, is_ref: bool, ptr_for_ref: bool) -> Option<&'b str> {
@@ -401,10 +437,9 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "bitcoin::secp256k1::Error" if !is_ref => Some("crate::c_types::Secp256k1Error"),
                        "bitcoin::blockdata::script::Script" if is_ref => Some("crate::c_types::u8slice"),
                        "bitcoin::blockdata::script::Script" if !is_ref => Some("crate::c_types::derived::CVec_u8Z"),
-                       "bitcoin::blockdata::transaction::OutPoint" if is_ref => Some("crate::chain::transaction::OutPoint"),
+                       "bitcoin::blockdata::transaction::OutPoint" => Some("crate::chain::transaction::OutPoint"),
                        "bitcoin::blockdata::transaction::Transaction" => Some("crate::c_types::Transaction"),
                        "bitcoin::blockdata::transaction::TxOut" if !is_ref => Some("crate::c_types::TxOut"),
-                       "bitcoin::OutPoint" => Some("crate::chain::transaction::OutPoint"),
                        "bitcoin::network::constants::Network" => Some("crate::bitcoin::network::Network"),
                        "bitcoin::blockdata::block::BlockHeader" if is_ref  => Some("*const [u8; 80]"),
                        "bitcoin::blockdata::block::Block" if is_ref  => Some("crate::c_types::u8slice"),
@@ -414,6 +449,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "bitcoin::hash_types::Txid" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"),
                        "bitcoin::hash_types::BlockHash" if is_ref  => Some("*const [u8; 32]"),
                        "bitcoin::hash_types::BlockHash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"),
+                       "bitcoin::secp256k1::Message" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"),
                        "ln::channelmanager::PaymentHash" if is_ref => Some("*const [u8; 32]"),
                        "ln::channelmanager::PaymentHash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes"),
                        "ln::channelmanager::PaymentPreimage" if is_ref => Some("*const [u8; 32]"),
@@ -550,7 +586,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
 
                        // List of structs we map (possibly during processing of other files):
                        "ln::features::InitFeatures" if is_ref => Some(".inner) }"),
-                       "ln::features::InitFeatures" if !is_ref => Some(".take_ptr()) }"),
+                       "ln::features::InitFeatures" if !is_ref => Some(".take_inner()) }"),
 
                        // List of traits we map (possibly during processing of other files):
                        "crate::util::logger::Logger" => Some(""),
@@ -614,6 +650,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "bitcoin::blockdata::script::Script" if is_ref => Some("crate::c_types::u8slice::from_slice(&"),
                        "bitcoin::blockdata::script::Script" if !is_ref => Some(""),
                        "bitcoin::blockdata::transaction::Transaction" => Some("crate::c_types::Transaction::from_vec(local_"),
+                       "bitcoin::blockdata::transaction::OutPoint" => Some("crate::c_types::bitcoin_to_C_outpoint("),
                        "bitcoin::blockdata::transaction::TxOut" if !is_ref => Some("crate::c_types::TxOut::from_rust("),
                        "bitcoin::blockdata::block::BlockHeader" if is_ref => Some("&local_"),
                        "bitcoin::blockdata::block::Block" if is_ref => Some("crate::c_types::u8slice::from_slice(&local_"),
@@ -624,6 +661,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "bitcoin::hash_types::Txid" if is_ref => Some(""),
                        "bitcoin::hash_types::BlockHash" if is_ref => Some(""),
                        "bitcoin::hash_types::BlockHash" => Some("crate::c_types::ThirtyTwoBytes { data: "),
+                       "bitcoin::secp256k1::Message" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "),
                        "ln::channelmanager::PaymentHash" if is_ref => Some("&"),
                        "ln::channelmanager::PaymentHash" if !is_ref => Some("crate::c_types::ThirtyTwoBytes { data: "),
                        "ln::channelmanager::PaymentPreimage" if is_ref => Some("&"),
@@ -677,6 +715,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "bitcoin::blockdata::script::Script" if is_ref => Some("[..])"),
                        "bitcoin::blockdata::script::Script" if !is_ref => Some(".into_bytes().into()"),
                        "bitcoin::blockdata::transaction::Transaction" => Some(")"),
+                       "bitcoin::blockdata::transaction::OutPoint" => Some(")"),
                        "bitcoin::blockdata::transaction::TxOut" if !is_ref => Some(")"),
                        "bitcoin::blockdata::block::BlockHeader" if is_ref => Some(""),
                        "bitcoin::blockdata::block::Block" if is_ref => Some(")"),
@@ -687,6 +726,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "bitcoin::hash_types::Txid" if is_ref => Some(".as_inner()"),
                        "bitcoin::hash_types::BlockHash" if is_ref => Some(".as_inner()"),
                        "bitcoin::hash_types::BlockHash" => Some(".into_inner() }"),
+                       "bitcoin::secp256k1::Message" if !is_ref => Some(".as_ref().clone() }"),
                        "ln::channelmanager::PaymentHash" if is_ref => Some(".0"),
                        "ln::channelmanager::PaymentHash" => Some(".0 }"),
                        "ln::channelmanager::PaymentPreimage" if is_ref => Some(".0"),
@@ -723,7 +763,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
 
        /// Returns the module path in the generated mapping crate to the containers which we generate
        /// when writing to CrateTypes::template_file.
-       fn generated_container_path() -> &'static str {
+       pub fn generated_container_path() -> &'static str {
                "crate::c_types::derived"
        }
        /// Returns the module path in the generated mapping crate to the container templates, which
@@ -794,8 +834,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                match full_path {
                        "Result" if !is_ref => {
                                Some(("match ",
-                                               vec![(".result_ok { true => Ok(".to_string(), format!("(*unsafe {{ Box::from_raw({}.contents.result.take_ptr()) }})", var_name)),
-                                                    ("), false => Err(".to_string(), format!("(*unsafe {{ Box::from_raw({}.contents.err.take_ptr()) }})", var_name))],
+                                               vec![(".result_ok { true => Ok(".to_string(), format!("(*unsafe {{ Box::from_raw(<*mut _>::take_ptr(&mut {}.contents.result)) }})", var_name)),
+                                                    ("), false => Err(".to_string(), format!("(*unsafe {{ Box::from_raw(<*mut _>::take_ptr(&mut {}.contents.err)) }})", var_name))],
                                                ")}"))
                        },
                        "Vec"|"Slice" if !is_ref => {
@@ -910,7 +950,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                self.declared.get(ident)
        }
        /// Returns true if the object at the given path is mapped as X { inner: *mut origX, .. }.
-       fn c_type_has_inner_from_path(&self, full_path: &str) -> bool{
+       pub fn c_type_has_inner_from_path(&self, full_path: &str) -> bool{
                self.crate_types.opaques.get(full_path).is_some()
        }
 
@@ -1057,7 +1097,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
        pub fn write_rust_type<W: std::io::Write>(&self, w: &mut W, generics: Option<&GenericTypes>, t: &syn::Type) {
                match t {
                        syn::Type::Path(p) => {
-                               if p.qself.is_some() || p.path.leading_colon.is_some() {
+                               if p.qself.is_some() {
                                        unimplemented!();
                                }
                                self.write_rust_path(w, generics, &p.path);
@@ -1406,7 +1446,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                |w, decl_type, _full_path, is_ref, _is_mut| match decl_type {
                                        DeclType::StructImported if is_ref && ptr_for_ref => write!(w, ").inner }}").unwrap(),
                                        DeclType::StructImported if is_ref => write!(w, ".inner }}").unwrap(),
-                                       DeclType::StructImported if !is_ref => write!(w, ".take_ptr()) }}").unwrap(),
+                                       DeclType::StructImported if !is_ref => write!(w, ".take_inner()) }}").unwrap(),
                                        DeclType::MirroredEnum if is_ref => write!(w, ".to_native()").unwrap(),
                                        DeclType::MirroredEnum => write!(w, ".into_native()").unwrap(),
                                        DeclType::Trait(_) => {},
@@ -1716,7 +1756,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
        // *** C Container Type Equivalent and alias Printing ***
        // ******************************************************
 
-       fn write_template_constructor<W: std::io::Write>(&mut self, w: &mut W, container_type: &str, mangled_container: &str, args: &Vec<&syn::Type>, generics: Option<&GenericTypes>, is_ref: bool) {
+       fn write_template_constructor<W: std::io::Write>(&mut self, w: &mut W, container_type: &str, mangled_container: &str, args: &Vec<&syn::Type>, generics: Option<&GenericTypes>, is_ref: bool) -> bool {
                if container_type == "Result" {
                        assert_eq!(args.len(), 2);
                        macro_rules! write_fn {
@@ -1734,14 +1774,14 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                        self.write_c_mangled_container_path_intern(w, Self::path_to_generic_args(path), generics,
                                                                &format!("{}", single_ident_generic_path_to_ident(path).unwrap()), is_ref, false, false, false);
                                                } else {
-                                                       self.write_template_generics(w, &mut [$item].iter().map(|t| *t), is_ref, true);
+                                                       self.write_template_generics(w, &mut [$item].iter().map(|t| *t), generics, is_ref, true);
                                                }
                                        } else if let syn::Type::Tuple(syn::TypeTuple { elems, .. }) = $item {
                                                self.write_c_mangled_container_path_intern(w, elems.iter().collect(), generics,
                                                        &format!("{}Tuple", elems.len()), is_ref, false, false, false);
                                        } else { unimplemented!(); }
                                        write!(w, ") -> {} =\n\t{}::CResultTempl::<", mangled_container, Self::container_templ_path()).unwrap();
-                                       self.write_template_generics(w, &mut args.iter().map(|t| *t), is_ref, true);
+                                       self.write_template_generics(w, &mut args.iter().map(|t| *t), generics, is_ref, true);
                                        writeln!(w, ">::{};\n", $call).unwrap();
                                } }
                        }
@@ -1757,7 +1797,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        write!(w, "#[no_mangle]\npub extern \"C\" fn {}_new(", mangled_container).unwrap();
                        for (idx, gen) in args.iter().enumerate() {
                                write!(w, "{}{}: ", if idx != 0 { ", " } else { "" }, ('a' as u8 + idx as u8) as char).unwrap();
-                               assert!(self.write_c_type_intern(w, gen, None, false, false, false));
+                               if !self.write_c_type_intern(w, gen, None, false, false, false) { return false; }
                        }
                        writeln!(w, ") -> {} {{", mangled_container).unwrap();
                        write!(w, "\t{} {{ ", mangled_container).unwrap();
@@ -1768,9 +1808,10 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                } else {
                        writeln!(w, "").unwrap();
                }
+               true
        }
 
-       fn write_template_generics<'b, W: std::io::Write>(&self, w: &mut W, args: &mut dyn Iterator<Item=&'b syn::Type>, is_ref: bool, in_crate: bool) {
+       fn write_template_generics<'b, W: std::io::Write>(&self, w: &mut W, args: &mut dyn Iterator<Item=&'b syn::Type>, generics: Option<&GenericTypes>, is_ref: bool, in_crate: bool) {
                for (idx, t) in args.enumerate() {
                        if idx != 0 {
                                write!(w, ", ").unwrap();
@@ -1780,11 +1821,11 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                        write!(w, "u8").unwrap();
                                } else {
                                        write!(w, "{}::C{}TupleTempl<", Self::container_templ_path(), tup.elems.len()).unwrap();
-                                       self.write_template_generics(w, &mut tup.elems.iter(), is_ref, in_crate);
+                                       self.write_template_generics(w, &mut tup.elems.iter(), generics, is_ref, in_crate);
                                        write!(w, ">").unwrap();
                                }
                        } else if let syn::Type::Path(p_arg) = t {
-                               let resolved_generic = self.resolve_path(&p_arg.path, None);
+                               let resolved_generic = self.resolve_path(&p_arg.path, generics);
                                if self.is_primitive(&resolved_generic) {
                                        write!(w, "{}", resolved_generic).unwrap();
                                } else if let Some(c_type) = self.c_type_from_path(&resolved_generic, is_ref, false) {
@@ -1794,19 +1835,19 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                if let syn::PathArguments::AngleBracketed(args) = &p_arg.path.segments.iter().next().unwrap().arguments {
                                                        self.write_template_generics(w, &mut args.args.iter().map(|gen|
                                                                if let syn::GenericArgument::Type(t) = gen { t } else { unimplemented!() }),
-                                                               is_ref, in_crate);
+                                                               generics, is_ref, in_crate);
                                                } else { unimplemented!(); }
                                                write!(w, ">").unwrap();
                                        } else if resolved_generic == "Option" {
                                                if let syn::PathArguments::AngleBracketed(args) = &p_arg.path.segments.iter().next().unwrap().arguments {
                                                        self.write_template_generics(w, &mut args.args.iter().map(|gen|
                                                                if let syn::GenericArgument::Type(t) = gen { t } else { unimplemented!() }),
-                                                               is_ref, in_crate);
+                                                               generics, is_ref, in_crate);
                                                } else { unimplemented!(); }
                                        } else if in_crate {
                                                write!(w, "{}", c_type).unwrap();
                                        } else {
-                                               self.write_rust_type(w, None, &t);
+                                               self.write_rust_type(w, generics, &t);
                                        }
                                } else {
                                        // If we just write out resolved_generic, it may mostly work, however for
@@ -1826,7 +1867,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                }
                        } else if let syn::Type::Reference(r_arg) = t {
                                if let syn::Type::Path(p_arg) = &*r_arg.elem {
-                                       let resolved = self.resolve_path(&p_arg.path, None);
+                                       let resolved = self.resolve_path(&p_arg.path, generics);
                                        if self.crate_types.opaques.get(&resolved).is_some() {
                                                write!(w, "crate::{}", resolved).unwrap();
                                        } else {
@@ -1836,7 +1877,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                } else { unimplemented!(); }
                        } else if let syn::Type::Array(a_arg) = t {
                                if let syn::Type::Path(p_arg) = &*a_arg.elem {
-                                       let resolved = self.resolve_path(&p_arg.path, None);
+                                       let resolved = self.resolve_path(&p_arg.path, generics);
                                        assert!(self.is_primitive(&resolved));
                                        if let syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Int(len), .. }) = &a_arg.len {
                                                write!(w, "{}",
@@ -1846,25 +1887,28 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        }
                }
        }
-       fn check_create_container(&mut self, mangled_container: String, container_type: &str, args: Vec<&syn::Type>, generics: Option<&GenericTypes>, is_ref: bool) {
+       fn check_create_container(&mut self, mangled_container: String, container_type: &str, args: Vec<&syn::Type>, generics: Option<&GenericTypes>, is_ref: bool) -> bool {
                if !self.crate_types.templates_defined.get(&mangled_container).is_some() {
-                       self.crate_types.templates_defined.insert(mangled_container.clone(), true);
                        let mut created_container: Vec<u8> = Vec::new();
 
-                       write!(&mut created_container, "#[no_mangle]\npub type {} = ", mangled_container).unwrap();
+                       write!(&mut created_container, "pub type {} = ", mangled_container).unwrap();
                        write!(&mut created_container, "{}::C{}Templ<", Self::container_templ_path(), container_type).unwrap();
-                       self.write_template_generics(&mut created_container, &mut args.iter().map(|t| *t), is_ref, true);
+                       self.write_template_generics(&mut created_container, &mut args.iter().map(|t| *t), generics, is_ref, true);
                        writeln!(&mut created_container, ">;").unwrap();
 
                        write!(&mut created_container, "#[no_mangle]\npub static {}_free: extern \"C\" fn({}) = ", mangled_container, mangled_container).unwrap();
                        write!(&mut created_container, "{}::C{}Templ_free::<", Self::container_templ_path(), container_type).unwrap();
-                       self.write_template_generics(&mut created_container, &mut args.iter().map(|t| *t), is_ref, true);
+                       self.write_template_generics(&mut created_container, &mut args.iter().map(|t| *t), generics, is_ref, true);
                        writeln!(&mut created_container, ">;").unwrap();
 
-                       self.write_template_constructor(&mut created_container, container_type, &mangled_container, &args, generics, is_ref);
+                       if !self.write_template_constructor(&mut created_container, container_type, &mangled_container, &args, generics, is_ref) {
+                               return false;
+                       }
+                       self.crate_types.templates_defined.insert(mangled_container.clone(), true);
 
                        self.crate_types.template_file.write(&created_container).unwrap();
                }
+               true
        }
        fn path_to_generic_args(path: &syn::Path) -> Vec<&syn::Type> {
                if let syn::PathArguments::AngleBracketed(args) = &path.segments.iter().next().unwrap().arguments {
@@ -1881,45 +1925,46 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                for arg in args.iter() {
                        macro_rules! write_path {
                                ($p_arg: expr, $extra_write: expr) => {
-                                       let subtype = self.resolve_path(&$p_arg.path, generics);
-                                       if self.is_transparent_container(ident, is_ref) {
-                                               // We dont (yet) support primitives or containers inside transparent
-                                               // containers, so check for that first:
-                                               if self.is_primitive(&subtype) { return false; }
-                                               if self.is_known_container(&subtype, is_ref) { return false; }
-                                               if !in_type {
-                                                       if self.c_type_has_inner_from_path(&subtype) {
-                                                               if !self.write_c_path_intern(w, &$p_arg.path, generics, is_ref, is_mut, ptr_for_ref) { return false; }
+                                       if let Some(subtype) = self.maybe_resolve_path(&$p_arg.path, generics) {
+                                               if self.is_transparent_container(ident, is_ref) {
+                                                       // We dont (yet) support primitives or containers inside transparent
+                                                       // containers, so check for that first:
+                                                       if self.is_primitive(&subtype) { return false; }
+                                                       if self.is_known_container(&subtype, is_ref) { return false; }
+                                                       if !in_type {
+                                                               if self.c_type_has_inner_from_path(&subtype) {
+                                                                       if !self.write_c_path_intern(w, &$p_arg.path, generics, is_ref, is_mut, ptr_for_ref) { return false; }
+                                                               } else {
+                                                                       // Option<T> needs to be converted to a *mut T, ie mut ptr-for-ref
+                                                                       if !self.write_c_path_intern(w, &$p_arg.path, generics, true, true, true) { return false; }
+                                                               }
                                                        } else {
-                                                               // Option<T> needs to be converted to a *mut T, ie mut ptr-for-ref
-                                                               if !self.write_c_path_intern(w, &$p_arg.path, generics, true, true, true) { return false; }
+                                                               if $p_arg.path.segments.len() == 1 {
+                                                                       write!(w, "{}", $p_arg.path.segments.iter().next().unwrap().ident).unwrap();
+                                                               } else {
+                                                                       return false;
+                                                               }
                                                        }
-                                               } else {
-                                                       if $p_arg.path.segments.len() == 1 {
-                                                               write!(w, "{}", $p_arg.path.segments.iter().next().unwrap().ident).unwrap();
-                                                       } else {
+                                               } else if self.is_known_container(&subtype, is_ref) || self.is_transparent_container(&subtype, is_ref) {
+                                                       if !self.write_c_mangled_container_path_intern(w, Self::path_to_generic_args(&$p_arg.path), generics,
+                                                                       &subtype, is_ref, is_mut, ptr_for_ref, true) {
                                                                return false;
                                                        }
-                                               }
-                                       } else if self.is_known_container(&subtype, is_ref) || self.is_transparent_container(&subtype, is_ref) {
-                                               if !self.write_c_mangled_container_path_intern(w, Self::path_to_generic_args(&$p_arg.path), generics,
-                                                               &subtype, is_ref, is_mut, ptr_for_ref, true) {
-                                                       return false;
-                                               }
-                                               self.write_c_mangled_container_path_intern(&mut mangled_type, Self::path_to_generic_args(&$p_arg.path),
-                                                       generics, &subtype, is_ref, is_mut, ptr_for_ref, true);
-                                               if let Some(w2) = $extra_write as Option<&mut Vec<u8>> {
-                                                       self.write_c_mangled_container_path_intern(w2, Self::path_to_generic_args(&$p_arg.path),
+                                                       self.write_c_mangled_container_path_intern(&mut mangled_type, Self::path_to_generic_args(&$p_arg.path),
                                                                generics, &subtype, is_ref, is_mut, ptr_for_ref, true);
+                                                       if let Some(w2) = $extra_write as Option<&mut Vec<u8>> {
+                                                               self.write_c_mangled_container_path_intern(w2, Self::path_to_generic_args(&$p_arg.path),
+                                                                       generics, &subtype, is_ref, is_mut, ptr_for_ref, true);
+                                                       }
+                                               } else {
+                                                       let id = &&$p_arg.path.segments.iter().rev().next().unwrap().ident;
+                                                       write!(w, "{}", id).unwrap();
+                                                       write!(mangled_type, "{}", id).unwrap();
+                                                       if let Some(w2) = $extra_write as Option<&mut Vec<u8>> {
+                                                               write!(w2, "{}", id).unwrap();
+                                                       }
                                                }
-                                       } else {
-                                               let id = &&$p_arg.path.segments.iter().rev().next().unwrap().ident;
-                                               write!(w, "{}", id).unwrap();
-                                               write!(mangled_type, "{}", id).unwrap();
-                                               if let Some(w2) = $extra_write as Option<&mut Vec<u8>> {
-                                                       write!(w2, "{}", id).unwrap();
-                                               }
-                                       }
+                                       } else { return false; }
                                }
                        }
                        if let syn::Type::Tuple(tuple) = arg {
@@ -1948,8 +1993,10 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                        write!(w, "Z").unwrap();
                                        write!(mangled_type, "Z").unwrap();
                                        write!(mangled_tuple_type, "Z").unwrap();
-                                       self.check_create_container(String::from_utf8(mangled_tuple_type).unwrap(),
-                                               &format!("{}Tuple", tuple.elems.len()), tuple.elems.iter().collect(), generics, is_ref);
+                                       if !self.check_create_container(String::from_utf8(mangled_tuple_type).unwrap(),
+                                                       &format!("{}Tuple", tuple.elems.len()), tuple.elems.iter().collect(), generics, is_ref) {
+                                               return false;
+                                       }
                                }
                        } else if let syn::Type::Path(p_arg) = arg {
                                write_path!(p_arg, None);
@@ -1983,8 +2030,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                write!(mangled_type, "Z").unwrap();
 
                // Make sure the type is actually defined:
-               self.check_create_container(String::from_utf8(mangled_type).unwrap(), ident, args, generics, is_ref);
-               true
+               self.check_create_container(String::from_utf8(mangled_type).unwrap(), ident, args, generics, is_ref)
        }
        fn write_c_mangled_container_path<W: std::io::Write>(&mut self, w: &mut W, args: Vec<&syn::Type>, generics: Option<&GenericTypes>, ident: &str, is_ref: bool, is_mut: bool, ptr_for_ref: bool) -> bool {
                if !self.is_transparent_container(ident, is_ref) {
@@ -2094,8 +2140,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                        format!("CVec_{}Z", id)
                                                } else { return false; };
                                                write!(w, "{}::{}", Self::generated_container_path(), mangled_container).unwrap();
-                                               self.check_create_container(mangled_container, "Vec", vec![&*r.elem], generics, false);
-                                               true
+                                               self.check_create_container(mangled_container, "Vec", vec![&*r.elem], generics, false)
                                        } else { false }
                                } else if let syn::Type::Tuple(_) = &*s.elem {
                                        let mut args = syn::punctuated::Punctuated::new();