Work around broken resolution on non-pub use aliasing in another module
[ldk-c-bindings] / c-bindings-gen / src / types.rs
index efd6b9afcb24e48bbfef296dcb5e01984816a6b4..b4b46a833a38e65bde039fabc348c68619a0fe44 100644 (file)
@@ -798,8 +798,8 @@ pub struct TypeResolver<'mod_lifetime, 'crate_lft: 'mod_lifetime> {
 enum EmptyValExpectedTy {
        /// A type which has a flag for being empty (eg an array where we treat all-0s as empty).
        NonPointer,
-       /// A pointer that we want to dereference and move out of.
-       OwnedPointer,
+       /// A Option mapped as a COption_*Z
+       OptionType,
        /// A pointer which we want to convert to a reference.
        ReferenceAsPointer,
 }
@@ -889,6 +889,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "std::time::SystemTime" => Some("u64"),
                        "std::io::Error" => Some("crate::c_types::IOError"),
 
+                       "core::convert::Infallible" => Some("crate::c_types::NotConstructable"),
+
                        "bech32::u5" => Some("crate::c_types::u5"),
                        "core::num::NonZeroU8" => Some("u8"),
 
@@ -931,6 +933,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        // Override the default since Records contain an fmt with a lifetime:
                        "lightning::util::logger::Record" => Some("*const std::os::raw::c_char"),
 
+                       "lightning::io::Read" => Some("crate::c_types::u8slice"),
+
                        _ => None,
                }
        }
@@ -965,6 +969,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        // Note that we'll panic for String if is_ref, as we only have non-owned memory, we
                        // cannot create a &String.
 
+                       "core::convert::Infallible" => Some("panic!(\"You must never construct a NotConstructable! : "),
+
                        "std::time::Duration"|"core::time::Duration" => Some("std::time::Duration::from_secs("),
                        "std::time::SystemTime" => Some("(::std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_secs("),
 
@@ -986,6 +992,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "bitcoin::blockdata::script::Script" if !is_ref => Some("::bitcoin::blockdata::script::Script::from("),
                        "bitcoin::blockdata::transaction::Transaction" if is_ref => Some("&"),
                        "bitcoin::blockdata::transaction::Transaction" => Some(""),
+                       "bitcoin::blockdata::transaction::OutPoint" => Some("crate::c_types::C_to_bitcoin_outpoint("),
                        "bitcoin::blockdata::transaction::TxOut" if !is_ref => Some(""),
                        "bitcoin::network::constants::Network" => Some(""),
                        "bitcoin::blockdata::block::BlockHeader" => Some("&::bitcoin::consensus::encode::deserialize(unsafe { &*"),
@@ -1013,6 +1020,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        // List of traits we map (possibly during processing of other files):
                        "crate::util::logger::Logger" => Some(""),
 
+                       "lightning::io::Read" => Some("&mut "),
+
                        _ => None,
                }.map(|s| s.to_owned())
        }
@@ -1040,6 +1049,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "alloc::string::String"|"String" => Some(".into_string()"),
                        "std::io::Error" if !is_ref => Some(".to_rust()"),
 
+                       "core::convert::Infallible" => Some("\")"),
+
                        "std::time::Duration"|"core::time::Duration" => Some(")"),
                        "std::time::SystemTime" => Some("))"),
 
@@ -1057,6 +1068,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "bitcoin::blockdata::script::Script" if is_ref => Some(".to_slice()))"),
                        "bitcoin::blockdata::script::Script" if !is_ref => Some(".into_rust())"),
                        "bitcoin::blockdata::transaction::Transaction" => Some(".into_bitcoin()"),
+                       "bitcoin::blockdata::transaction::OutPoint" => Some(")"),
                        "bitcoin::blockdata::transaction::TxOut" if !is_ref => Some(".into_rust()"),
                        "bitcoin::network::constants::Network" => Some(".into_bitcoin()"),
                        "bitcoin::blockdata::block::BlockHeader" => Some(" }).unwrap()"),
@@ -1079,6 +1091,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        // List of traits we map (possibly during processing of other files):
                        "crate::util::logger::Logger" => Some(""),
 
+                       "lightning::io::Read" => Some(".to_reader()"),
+
                        _ => None,
                }.map(|s| s.to_owned())
        }
@@ -1128,6 +1142,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "std::time::SystemTime" => Some(""),
                        "std::io::Error" if !is_ref => Some("crate::c_types::IOError::from_rust("),
 
+                       "core::convert::Infallible" => Some("panic!(\"Cannot construct an Infallible: "),
+
                        "bech32::u5" => Some(""),
 
                        "bitcoin::secp256k1::key::PublicKey"|"bitcoin::secp256k1::PublicKey"|"secp256k1::key::PublicKey"
@@ -1167,6 +1183,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        // Override the default since Records contain an fmt with a lifetime:
                        "lightning::util::logger::Record" => Some("local_"),
 
+                       "lightning::io::Read" => Some("crate::c_types::u8slice::from_vec(&crate::c_types::reader_to_vec("),
+
                        _ => None,
                }.map(|s| s.to_owned())
        }
@@ -1198,6 +1216,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        "std::time::SystemTime" => Some(".duration_since(::std::time::SystemTime::UNIX_EPOCH).expect(\"Times must be post-1970\").as_secs()"),
                        "std::io::Error" if !is_ref => Some(")"),
 
+                       "core::convert::Infallible" => Some("\")"),
+
                        "bech32::u5" => Some(".into()"),
 
                        "bitcoin::secp256k1::key::PublicKey"|"bitcoin::secp256k1::PublicKey"|"secp256k1::key::PublicKey"
@@ -1236,6 +1256,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        // Override the default since Records contain an fmt with a lifetime:
                        "lightning::util::logger::Record" => Some(".as_ptr()"),
 
+                       "lightning::io::Read" => Some("))"),
+
                        _ => None,
                }.map(|s| s.to_owned())
        }
@@ -1249,6 +1271,18 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                }
        }
 
+       /// When printing a reference to the source crate's rust type, if we need to map it to a
+       /// different "real" type, it can be done so here.
+       /// This is useful to work around limitations in the binding type resolver, where we reference
+       /// a non-public `use` alias.
+       /// TODO: We should never need to use this!
+       fn real_rust_type_mapping<'equiv>(&self, thing: &'equiv str) -> &'equiv str {
+               match thing {
+                       "lightning::io::Read" => "std::io::Read",
+                       _ => thing,
+               }
+       }
+
        // ****************************
        // *** Container Processing ***
        // ****************************
@@ -1266,15 +1300,17 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
 
        /// Returns true if the path containing the given args is a "transparent" container, ie an
        /// Option or a container which does not require a generated continer class.
-       fn is_transparent_container<'i, I: Iterator<Item=&'i syn::Type>>(&self, full_path: &str, _is_ref: bool, mut args: I) -> bool {
+       fn is_transparent_container<'i, I: Iterator<Item=&'i syn::Type>>(&self, full_path: &str, _is_ref: bool, mut args: I, generics: Option<&GenericTypes>) -> bool {
                if full_path == "Option" {
                        let inner = args.next().unwrap();
                        assert!(args.next().is_none());
                        match inner {
                                syn::Type::Reference(_) => true,
                                syn::Type::Path(p) => {
-                                       if let Some(resolved) = self.maybe_resolve_path(&p.path, None) {
-                                               if self.is_primitive(&resolved) { false } else { true }
+                                       if let Some(resolved) = self.maybe_resolve_path(&p.path, generics) {
+                                               if self.c_type_has_inner_from_path(&resolved) { return true; }
+                                               if self.is_primitive(&resolved) { return false; }
+                                               if self.c_type_from_path(&resolved, false, false).is_some() { true } else { false }
                                        } else { true }
                                },
                                syn::Type::Tuple(_) => false,
@@ -1294,7 +1330,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        }),
                        syn::PathArguments::Parenthesized(_) => unimplemented!(),
                };
-               self.is_transparent_container(&self.resolve_path(full_path, generics), is_ref, inner_iter)
+               self.is_transparent_container(&self.resolve_path(full_path, generics), is_ref, inner_iter, generics)
        }
        /// Returns true if this is a known, supported, non-transparent container.
        fn is_known_container(&self, full_path: &str, is_ref: bool) -> bool {
@@ -1330,12 +1366,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                        } else { None }
                                } else { None };
                                if let Some(inner_path) = contained_struct {
-                                       if self.is_primitive(&inner_path) {
-                                               return Some(("if ", vec![
-                                                       (format!(".is_none() {{ {}::COption_{}Z::None }} else {{ ", Self::generated_container_path(), inner_path),
-                                                        format!("{}::COption_{}Z::Some({}.unwrap())", Self::generated_container_path(), inner_path, var_access))
-                                                       ], " }", ContainerPrefixLocation::NoPrefix));
-                                       } else if self.c_type_has_inner_from_path(&inner_path) {
+                                       if self.c_type_has_inner_from_path(&inner_path) {
                                                let is_inner_ref = if let Some(syn::Type::Reference(_)) = single_contained { true } else { false };
                                                if is_ref {
                                                        return Some(("if ", vec![
@@ -1347,6 +1378,16 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                                (".is_none() { std::ptr::null_mut() } else { ".to_owned(), format!("({}.unwrap())", var_access))
                                                                ], " }", ContainerPrefixLocation::OutsideConv));
                                                }
+                                       } else if self.is_primitive(&inner_path) || self.c_type_from_path(&inner_path, false, false).is_none() {
+                                               let inner_name = inner_path.rsplit("::").next().unwrap();
+                                               return Some(("if ", vec![
+                                                       (format!(".is_none() {{ {}::COption_{}Z::None }} else {{ {}::COption_{}Z::Some(",
+                                                               Self::generated_container_path(), inner_name, Self::generated_container_path(), inner_name),
+                                                        format!("{}.unwrap()", var_access))
+                                                       ], ") }", ContainerPrefixLocation::PerConv));
+                                       } else {
+                                               // If c_type_from_path is some (ie there's a manual mapping for the inner
+                                               // type), lean on write_empty_rust_val, below.
                                        }
                                }
                                if let Some(t) = single_contained {
@@ -1406,14 +1447,11 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                                        return Some(("if ", vec![
                                                                                (format!("{} {{ None }} else {{ Some(", s), format!("unsafe {{ &mut *{} }}", var_access))
                                                                        ], ") }", ContainerPrefixLocation::NoPrefix)),
-                                                               EmptyValExpectedTy::OwnedPointer => {
-                                                                       if let syn::Type::Slice(_) = t {
-                                                                                       panic!();
-                                                                       }
-                                                                       return Some(("if ", vec![
-                                                                               (format!("{} {{ None }} else {{ Some(", s), format!("unsafe {{ *Box::from_raw({}) }}", var_access))
-                                                                       ], ") }", ContainerPrefixLocation::NoPrefix));
-                                                               }
+                                                               EmptyValExpectedTy::OptionType =>
+                                                                       return Some(("{ /* ", vec![
+                                                                               (format!("*/ let {}_opt = {};", var_name, var_access),
+                                                                               format!("}} if {}_opt{} {{ None }} else {{ Some({{ {}_opt.take()", var_name, s, var_name))
+                                                                       ], ") } }", ContainerPrefixLocation::PerConv)),
                                                                EmptyValExpectedTy::NonPointer =>
                                                                        return Some(("if ", vec![
                                                                                (format!("{} {{ None }} else {{ Some(", s), format!("{}", var_access))
@@ -1437,7 +1475,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                let default_value = Some(syn::Type::Reference(syn::TypeReference {
                        and_token: syn::Token!(&)(Span::call_site()), lifetime: None, mutability: None,
                        elem: Box::new(t.clone()) }));
-               match t {
+               match generics.resolve_type(t) {
                        syn::Type::Path(p) => {
                                if let Some(resolved_path) = self.maybe_resolve_path(&p.path, generics) {
                                        if resolved_path != "Vec" { return default_value; }
@@ -1541,7 +1579,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                // If we're printing a generic argument, it needs to reference the crate, otherwise
                                // the original crate:
                                } else if self.maybe_resolve_path(&path, None).as_ref() == Some(&resolved) {
-                                       write!(w, "{}", resolved).unwrap();
+                                       write!(w, "{}", self.real_rust_type_mapping(&resolved)).unwrap();
                                } else {
                                        write!(w, "crate::{}", resolved).unwrap();
                                }
@@ -1715,8 +1753,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                // We may eventually need to allow empty_val_check_suffix_from_path to specify if we need a deref or not
                                                EmptyValExpectedTy::NonPointer
                                        } else {
-                                               write!(w, " == std::ptr::null_mut()").unwrap();
-                                               EmptyValExpectedTy::OwnedPointer
+                                               write!(w, ".is_none()").unwrap();
+                                               EmptyValExpectedTy::OptionType
                                        }
                                }
                        },
@@ -2156,7 +2194,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                        if let syn::PathArguments::AngleBracketed(args) = &p.path.segments.iter().next().unwrap().arguments {
                                                convert_container!(resolved_path, args.args.len(), || args.args.iter().map(|arg| {
                                                        if let syn::GenericArgument::Type(ty) = arg {
-                                                               ty
+                                                               generics.resolve_type(ty)
                                                        } else { unimplemented!(); }
                                                }));
                                        } else { unimplemented!(); }
@@ -2189,7 +2227,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                } else if let syn::Type::Reference(ty) = &*s.elem {
                                        let tyref = [&*ty.elem];
                                        is_ref = true;
-                                       convert_container!("Slice", 1, || tyref.iter().map(|t| *t));
+                                       convert_container!("Slice", 1, || tyref.iter().map(|t| generics.resolve_type(*t)));
                                        unimplemented!("convert_container should return true as container_lookup should succeed for slices");
                                } else if let syn::Type::Tuple(t) = &*s.elem {
                                        // When mapping into a temporary new var, we need to own all the underlying objects.
@@ -2419,7 +2457,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
        fn write_c_mangled_container_path_intern<W: std::io::Write>
                        (&self, w: &mut W, args: Vec<&syn::Type>, generics: Option<&GenericTypes>, ident: &str, is_ref: bool, is_mut: bool, ptr_for_ref: bool, in_type: bool) -> bool {
                let mut mangled_type: Vec<u8> = Vec::new();
-               if !self.is_transparent_container(ident, is_ref, args.iter().map(|a| *a)) {
+               if !self.is_transparent_container(ident, is_ref, args.iter().map(|a| *a), generics) {
                        write!(w, "C{}_", ident).unwrap();
                        write!(mangled_type, "C{}_", ident).unwrap();
                } else { assert_eq!(args.len(), 1); }
@@ -2427,7 +2465,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        macro_rules! write_path {
                                ($p_arg: expr, $extra_write: expr) => {
                                        if let Some(subtype) = self.maybe_resolve_path(&$p_arg.path, generics) {
-                                               if self.is_transparent_container(ident, is_ref, args.iter().map(|a| *a)) {
+                                               if self.is_transparent_container(ident, is_ref, args.iter().map(|a| *a), generics) {
                                                        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; }
@@ -2464,64 +2502,70 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                        } else { return false; }
                                }
                        }
-                       if let syn::Type::Tuple(tuple) = arg {
-                               if tuple.elems.len() == 0 {
-                                       write!(w, "None").unwrap();
-                                       write!(mangled_type, "None").unwrap();
-                               } else {
-                                       let mut mangled_tuple_type: Vec<u8> = Vec::new();
-
-                                       // Figure out what the mangled type should look like. To disambiguate
-                                       // ((A, B), C) and (A, B, C) we prefix the generic args with a _ and suffix
-                                       // them with a Z. Ideally we wouldn't use Z, but not many special chars are
-                                       // available for use in type names.
-                                       write!(w, "C{}Tuple_", tuple.elems.len()).unwrap();
-                                       write!(mangled_type, "C{}Tuple_", tuple.elems.len()).unwrap();
-                                       write!(mangled_tuple_type, "C{}Tuple_", tuple.elems.len()).unwrap();
-                                       for elem in tuple.elems.iter() {
-                                               if let syn::Type::Path(p) = elem {
-                                                       write_path!(p, Some(&mut mangled_tuple_type));
-                                               } else if let syn::Type::Reference(refelem) = elem {
-                                                       if let syn::Type::Path(p) = &*refelem.elem {
+                       match generics.resolve_type(arg) {
+                               syn::Type::Tuple(tuple) => {
+                                       if tuple.elems.len() == 0 {
+                                               write!(w, "None").unwrap();
+                                               write!(mangled_type, "None").unwrap();
+                                       } else {
+                                               let mut mangled_tuple_type: Vec<u8> = Vec::new();
+
+                                               // Figure out what the mangled type should look like. To disambiguate
+                                               // ((A, B), C) and (A, B, C) we prefix the generic args with a _ and suffix
+                                               // them with a Z. Ideally we wouldn't use Z, but not many special chars are
+                                               // available for use in type names.
+                                               write!(w, "C{}Tuple_", tuple.elems.len()).unwrap();
+                                               write!(mangled_type, "C{}Tuple_", tuple.elems.len()).unwrap();
+                                               write!(mangled_tuple_type, "C{}Tuple_", tuple.elems.len()).unwrap();
+                                               for elem in tuple.elems.iter() {
+                                                       if let syn::Type::Path(p) = elem {
                                                                write_path!(p, Some(&mut mangled_tuple_type));
+                                                       } else if let syn::Type::Reference(refelem) = elem {
+                                                               if let syn::Type::Path(p) = &*refelem.elem {
+                                                                       write_path!(p, Some(&mut mangled_tuple_type));
+                                                               } else { return false; }
                                                        } else { return false; }
-                                               } else { return false; }
-                                       }
-                                       write!(w, "Z").unwrap();
-                                       write!(mangled_type, "Z").unwrap();
-                                       write!(mangled_tuple_type, "Z").unwrap();
-                                       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;
+                                               }
+                                               write!(w, "Z").unwrap();
+                                               write!(mangled_type, "Z").unwrap();
+                                               write!(mangled_tuple_type, "Z").unwrap();
+                                               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);
-                       } else if let syn::Type::Reference(refty) = arg {
-                               if let syn::Type::Path(p_arg) = &*refty.elem {
+                               },
+                               syn::Type::Path(p_arg) => {
                                        write_path!(p_arg, None);
-                               } else if let syn::Type::Slice(_) = &*refty.elem {
-                                       // write_c_type will actually do exactly what we want here, we just need to
-                                       // make it a pointer so that its an option. Note that we cannot always convert
-                                       // the Vec-as-slice (ie non-ref types) containers, so sometimes need to be able
-                                       // to edit it, hence we use *mut here instead of *const.
-                                       if args.len() != 1 { return false; }
-                                       write!(w, "*mut ").unwrap();
-                                       self.write_c_type(w, arg, None, true);
-                               } else { return false; }
-                       } else if let syn::Type::Array(a) = arg {
-                               if let syn::Type::Path(p_arg) = &*a.elem {
-                                       let resolved = self.resolve_path(&p_arg.path, generics);
-                                       if !self.is_primitive(&resolved) { return false; }
-                                       if let syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Int(len), .. }) = &a.len {
-                                               if self.c_type_from_path(&format!("[{}; {}]", resolved, len.base10_digits()), is_ref, ptr_for_ref).is_none() { return false; }
-                                               write!(w, "_{}{}", resolved, len.base10_digits()).unwrap();
-                                               write!(mangled_type, "_{}{}", resolved, len.base10_digits()).unwrap();
+                               },
+                               syn::Type::Reference(refty) => {
+                                       if let syn::Type::Path(p_arg) = &*refty.elem {
+                                               write_path!(p_arg, None);
+                                       } else if let syn::Type::Slice(_) = &*refty.elem {
+                                               // write_c_type will actually do exactly what we want here, we just need to
+                                               // make it a pointer so that its an option. Note that we cannot always convert
+                                               // the Vec-as-slice (ie non-ref types) containers, so sometimes need to be able
+                                               // to edit it, hence we use *mut here instead of *const.
+                                               if args.len() != 1 { return false; }
+                                               write!(w, "*mut ").unwrap();
+                                               self.write_c_type(w, arg, None, true);
                                        } else { return false; }
-                               } else { return false; }
-                       } else { return false; }
+                               },
+                               syn::Type::Array(a) => {
+                                       if let syn::Type::Path(p_arg) = &*a.elem {
+                                               let resolved = self.resolve_path(&p_arg.path, generics);
+                                               if !self.is_primitive(&resolved) { return false; }
+                                               if let syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Int(len), .. }) = &a.len {
+                                                       if self.c_type_from_path(&format!("[{}; {}]", resolved, len.base10_digits()), is_ref, ptr_for_ref).is_none() { return false; }
+                                                       write!(w, "_{}{}", resolved, len.base10_digits()).unwrap();
+                                                       write!(mangled_type, "_{}{}", resolved, len.base10_digits()).unwrap();
+                                               } else { return false; }
+                                       } else { return false; }
+                               },
+                               _ => { return false; },
+                       }
                }
-               if self.is_transparent_container(ident, is_ref, args.iter().map(|a| *a)) { return true; }
+               if self.is_transparent_container(ident, is_ref, args.iter().map(|a| *a), generics) { return true; }
                // Push the "end of type" Z
                write!(w, "Z").unwrap();
                write!(mangled_type, "Z").unwrap();
@@ -2530,7 +2574,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                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>(&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, args.iter().map(|a| *a)) {
+               if !self.is_transparent_container(ident, is_ref, args.iter().map(|a| *a), generics) {
                        write!(w, "{}::", Self::generated_container_path()).unwrap();
                }
                self.write_c_mangled_container_path_intern(w, args, generics, ident, is_ref, is_mut, ptr_for_ref, false)