[bindings] Drop useless `#[no_mangle]` from `pub type` definitions
[rust-lightning] / c-bindings-gen / src / types.rs
index 14b2826f1e8b880824ebc8191398d771e64e6396..e3ae3bdef4f9012fd2b7014466f419b7080c8e19 100644 (file)
@@ -1,6 +1,7 @@
 use std::collections::HashMap;
 use std::fs::File;
 use std::io::Write;
+use std::hash;
 
 use proc_macro2::{TokenTree, Span};
 
@@ -32,11 +33,6 @@ pub fn get_single_remaining_path_seg<'a, I: Iterator<Item=&'a syn::PathSegment>>
        } else { None }
 }
 
-pub fn assert_single_path_seg<'a>(p: &'a syn::Path) -> &'a syn::Ident {
-       if p.leading_colon.is_some() { unimplemented!(); }
-       get_single_remaining_path_seg(&mut p.segments.iter()).unwrap()
-}
-
 pub fn single_ident_generic_path_to_ident(p: &syn::Path) -> Option<&syn::Ident> {
        if p.segments.len() == 1 {
                Some(&p.segments.iter().next().unwrap().ident)
@@ -133,6 +129,7 @@ impl<'a> GenericTypes<'a> {
 
        /// Learn the generics in generics in the current context, given a TypeResolver.
        pub fn learn_generics<'b, 'c>(&mut self, generics: &'a syn::Generics, types: &'b TypeResolver<'a, 'c>) -> bool {
+               // First learn simple generics...
                for generic in generics.params.iter() {
                        match generic {
                                syn::GenericParam::Type(type_param) => {
@@ -160,6 +157,7 @@ impl<'a> GenericTypes<'a> {
                                _ => {},
                        }
                }
+               // Then find generics where we are required to pass a Deref<Target=X> and pretend its just X.
                if let Some(wh) = &generics.where_clause {
                        for pred in wh.predicates.iter() {
                                if let syn::WherePredicate::Type(t) = pred {
@@ -192,6 +190,38 @@ impl<'a> GenericTypes<'a> {
                true
        }
 
+       /// Learn the associated types from the trait in the current context.
+       pub fn learn_associated_types<'b, 'c>(&mut self, t: &'a syn::ItemTrait, types: &'b TypeResolver<'a, 'c>) {
+               for item in t.items.iter() {
+                       match item {
+                               &syn::TraitItem::Type(ref t) => {
+                                       if t.default.is_some() || t.generics.lt_token.is_some() { unimplemented!(); }
+                                       let mut bounds_iter = t.bounds.iter();
+                                       match bounds_iter.next().unwrap() {
+                                               syn::TypeParamBound::Trait(tr) => {
+                                                       assert_simple_bound(&tr);
+                                                       if let Some(mut path) = types.maybe_resolve_path(&tr.path, None) {
+                                                               if types.skip_path(&path) { continue; }
+                                                               // In general we handle Deref<Target=X> as if it were just X (and
+                                                               // implement Deref<Target=Self> for relevant types). We don't
+                                                               // bother to implement it for associated types, however, so we just
+                                                               // ignore such bounds.
+                                                               let new_ident = if path != "std::ops::Deref" {
+                                                                       path = "crate::".to_string() + &path;
+                                                                       Some(&tr.path)
+                                                               } else { None };
+                                                               self.typed_generics.last_mut().unwrap().insert(&t.ident, (path, new_ident));
+                                                       } else { unimplemented!(); }
+                                               },
+                                               _ => unimplemented!(),
+                                       }
+                                       if bounds_iter.next().is_some() { unimplemented!(); }
+                               },
+                               _ => {},
+                       }
+               }
+       }
+
        /// Attempt to resolve an Ident as a generic parameter and return the full path.
        pub fn maybe_resolve_ident<'b>(&'b self, ident: &syn::Ident) -> Option<&'b String> {
                for gen in self.typed_generics.iter().rev() {
@@ -210,6 +240,18 @@ impl<'a> GenericTypes<'a> {
                                        return Some(res);
                                }
                        }
+               } else {
+                       // Associated types are usually specified as "Self::Generic", so we check for that
+                       // explicitly here.
+                       let mut it = path.segments.iter();
+                       if path.segments.len() == 2 && format!("{}", it.next().unwrap().ident) == "Self" {
+                               let ident = &it.next().unwrap().ident;
+                               for gen in self.typed_generics.iter().rev() {
+                                       if let Some(res) = gen.get(ident).map(|(a, b)| (a, b.unwrap())) {
+                                               return Some(res);
+                                       }
+                               }
+                       }
                }
                None
        }
@@ -225,6 +267,13 @@ pub enum DeclType<'a> {
        EnumIgnored,
 }
 
+// templates_defined is walked to write the C++ header, so if we use the default hashing it get
+// reordered on each genbindings run. Instead, we use SipHasher (which defaults to 0-keys) so that
+// the sorting is stable across runs. It is deprecated, but the "replacement" doesn't actually
+// accomplish the same goals, so we just ignore it.
+#[allow(deprecated)]
+type NonRandomHash = hash::BuildHasherDefault<hash::SipHasher>;
+
 /// Top-level struct tracking everything which has been defined while walking the crate.
 pub struct CrateTypes<'a> {
        /// This may contain structs or enums, but only when either is mapped as
@@ -234,11 +283,13 @@ pub struct CrateTypes<'a> {
        pub mirrored_enums: HashMap<String, &'a syn::ItemEnum>,
        /// Traits which are mapped as a pointer + jump table
        pub traits: HashMap<String, &'a syn::ItemTrait>,
+       /// Aliases from paths to some other Type
+       pub type_aliases: HashMap<String, syn::Type>,
        /// Template continer types defined, map from mangled type name -> whether a destructor fn
        /// exists.
        ///
        /// This is used at the end of processing to make C++ wrapper classes
-       pub templates_defined: HashMap<String, bool>,
+       pub templates_defined: HashMap<String, bool, NonRandomHash>,
        /// 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,
@@ -255,6 +306,17 @@ pub struct TypeResolver<'mod_lifetime, 'crate_lft: 'mod_lifetime> {
        pub crate_types: &'mod_lifetime mut CrateTypes<'crate_lft>,
 }
 
+/// Returned by write_empty_rust_val_check_suffix to indicate what type of dereferencing needs to
+/// happen to get the inner value of a generic.
+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 pointer which we want to convert to a reference.
+       ReferenceAsPointer,
+}
+
 impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
        pub fn new(orig_crate: &'a str, module_path: &'a str, crate_types: &'a mut CrateTypes<'c>) -> Self {
                let mut imports = HashMap::new();
@@ -339,10 +401,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"),
@@ -352,6 +413,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]"),
@@ -488,7 +550,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(""),
@@ -552,6 +614,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_"),
@@ -562,6 +625,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("&"),
@@ -615,6 +679,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(")"),
@@ -625,6 +690,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"),
@@ -732,8 +798,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 => {
@@ -755,20 +821,21 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
 
                                if let Some(t) = single_contained {
                                        let mut v = Vec::new();
-                                       let (needs_deref, ret_ref) = self.write_empty_rust_val_check_suffix(generics, &mut v, t);
+                                       let ret_ref = self.write_empty_rust_val_check_suffix(generics, &mut v, t);
                                        let s = String::from_utf8(v).unwrap();
-                                       if needs_deref && ret_ref {
-                                               return Some(("if ", vec![
-                                                       (format!("{} {{ None }} else {{ Some(", s), format!("unsafe {{ &mut *{} }}", var_access))
-                                               ], ") }"));
-                                       } else if needs_deref {
-                                               return Some(("if ", vec![
-                                                       (format!("{} {{ None }} else {{ Some(", s), format!("unsafe {{ *Box::from_raw({}) }}", var_access))
-                                               ], ") }"));
-                                       } else {
-                                               return Some(("if ", vec![
-                                                       (format!("{} {{ None }} else {{ Some(", s), format!("{}", var_access))
-                                               ], ") }"));
+                                       match ret_ref {
+                                               EmptyValExpectedTy::ReferenceAsPointer =>
+                                                       return Some(("if ", vec![
+                                                               (format!("{} {{ None }} else {{ Some(", s), format!("unsafe {{ &mut *{} }}", var_access))
+                                                       ], ") }")),
+                                               EmptyValExpectedTy::OwnedPointer =>
+                                                       return Some(("if ", vec![
+                                                               (format!("{} {{ None }} else {{ Some(", s), format!("unsafe {{ *Box::from_raw({}) }}", var_access))
+                                                       ], ") }")),
+                                               EmptyValExpectedTy::NonPointer =>
+                                                       return Some(("if ", vec![
+                                                               (format!("{} {{ None }} else {{ Some(", s), format!("{}", var_access))
+                                                       ], ") }")),
                                        }
                                } else { unreachable!(); }
                        },
@@ -910,19 +977,34 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
        // *** Original Rust Type Printing ***
        // ***********************************
 
-       fn write_rust_path<W: std::io::Write>(&self, w: &mut W, path: &syn::Path) {
-               if let Some(resolved) = self.maybe_resolve_path(&path, None) {
+       fn in_rust_prelude(resolved_path: &str) -> bool {
+               match resolved_path {
+                       "Vec" => true,
+                       "Result" => true,
+                       "Option" => true,
+                       _ => false,
+               }
+       }
+
+       fn write_rust_path<W: std::io::Write>(&self, w: &mut W, generics_resolver: Option<&GenericTypes>, path: &syn::Path) {
+               if let Some(resolved) = self.maybe_resolve_path(&path, generics_resolver) {
                        if self.is_primitive(&resolved) {
                                write!(w, "{}", path.get_ident().unwrap()).unwrap();
                        } else {
-                               if resolved.starts_with("ln::") || resolved.starts_with("chain::") || resolved.starts_with("util::") {
-                                       write!(w, "lightning::{}", resolved).unwrap();
+                               // TODO: We should have a generic "is from a dependency" check here instead of
+                               // checking for "bitcoin" explicitly.
+                               if resolved.starts_with("bitcoin::") || Self::in_rust_prelude(&resolved) {
+                                       write!(w, "{}", resolved).unwrap();
+                               // 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, "{}::{}", self.orig_crate, resolved).unwrap();
                                } else {
-                                       write!(w, "{}", resolved).unwrap(); // XXX: Probably doens't work, get_ident().unwrap()
+                                       write!(w, "crate::{}", resolved).unwrap();
                                }
                        }
                        if let syn::PathArguments::AngleBracketed(args) = &path.segments.iter().last().unwrap().arguments {
-                               self.write_rust_generic_arg(w, args.args.iter());
+                               self.write_rust_generic_arg(w, generics_resolver, args.args.iter());
                        }
                } else {
                        if path.leading_colon.is_some() {
@@ -932,12 +1014,12 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                if idx != 0 { write!(w, "::").unwrap(); }
                                write!(w, "{}", seg.ident).unwrap();
                                if let syn::PathArguments::AngleBracketed(args) = &seg.arguments {
-                                       self.write_rust_generic_arg(w, args.args.iter());
+                                       self.write_rust_generic_arg(w, generics_resolver, args.args.iter());
                                }
                        }
                }
        }
-       pub fn write_rust_generic_param<'b, W: std::io::Write>(&self, w: &mut W, generics: impl Iterator<Item=&'b syn::GenericParam>) {
+       pub fn write_rust_generic_param<'b, W: std::io::Write>(&self, w: &mut W, generics_resolver: Option<&GenericTypes>, generics: impl Iterator<Item=&'b syn::GenericParam>) {
                let mut had_params = false;
                for (idx, arg) in generics.enumerate() {
                        if idx != 0 { write!(w, ", ").unwrap(); } else { write!(w, "<").unwrap(); }
@@ -952,7 +1034,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                match bound {
                                                        syn::TypeParamBound::Trait(tb) => {
                                                                if tb.paren_token.is_some() || tb.lifetimes.is_some() { unimplemented!(); }
-                                                               self.write_rust_path(w, &tb.path);
+                                                               self.write_rust_path(w, generics_resolver, &tb.path);
                                                        },
                                                        _ => unimplemented!(),
                                                }
@@ -965,24 +1047,24 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                if had_params { write!(w, ">").unwrap(); }
        }
 
-       pub fn write_rust_generic_arg<'b, W: std::io::Write>(&self, w: &mut W, generics: impl Iterator<Item=&'b syn::GenericArgument>) {
+       pub fn write_rust_generic_arg<'b, W: std::io::Write>(&self, w: &mut W, generics_resolver: Option<&GenericTypes>, generics: impl Iterator<Item=&'b syn::GenericArgument>) {
                write!(w, "<").unwrap();
                for (idx, arg) in generics.enumerate() {
                        if idx != 0 { write!(w, ", ").unwrap(); }
                        match arg {
-                               syn::GenericArgument::Type(t) => self.write_rust_type(w, t),
+                               syn::GenericArgument::Type(t) => self.write_rust_type(w, generics_resolver, t),
                                _ => unimplemented!(),
                        }
                }
                write!(w, ">").unwrap();
        }
-       pub fn write_rust_type<W: std::io::Write>(&self, w: &mut W, t: &syn::Type) {
+       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() {
                                        unimplemented!();
                                }
-                               self.write_rust_path(w, &p.path);
+                               self.write_rust_path(w, generics, &p.path);
                        },
                        syn::Type::Reference(r) => {
                                write!(w, "&").unwrap();
@@ -992,11 +1074,11 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                if r.mutability.is_some() {
                                        write!(w, "mut ").unwrap();
                                }
-                               self.write_rust_type(w, &*r.elem);
+                               self.write_rust_type(w, generics, &*r.elem);
                        },
                        syn::Type::Array(a) => {
                                write!(w, "[").unwrap();
-                               self.write_rust_type(w, &a.elem);
+                               self.write_rust_type(w, generics, &a.elem);
                                if let syn::Expr::Lit(l) = &a.len {
                                        if let syn::Lit::Int(i) = &l.lit {
                                                write!(w, "; {}]", i).unwrap();
@@ -1005,14 +1087,14 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        }
                        syn::Type::Slice(s) => {
                                write!(w, "[").unwrap();
-                               self.write_rust_type(w, &s.elem);
+                               self.write_rust_type(w, generics, &s.elem);
                                write!(w, "]").unwrap();
                        },
                        syn::Type::Tuple(s) => {
                                write!(w, "(").unwrap();
                                for (idx, t) in s.elems.iter().enumerate() {
                                        if idx != 0 { write!(w, ", ").unwrap(); }
-                                       self.write_rust_type(w, &t);
+                                       self.write_rust_type(w, generics, &t);
                                }
                                write!(w, ")").unwrap();
                        },
@@ -1052,23 +1134,23 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                }
        }
 
-       /// Prints a suffix to determine if a variable is empty (ie was set by write_empty_rust_val),
-       /// returning whether we need to dereference the inner value before using it (ie it is a
-       /// pointer).
-       pub fn write_empty_rust_val_check_suffix<W: std::io::Write>(&self, generics: Option<&GenericTypes>, w: &mut W, t: &syn::Type) -> (bool, bool) {
+       /// Prints a suffix to determine if a variable is empty (ie was set by write_empty_rust_val).
+       /// See EmptyValExpectedTy for information on return types.
+       fn write_empty_rust_val_check_suffix<W: std::io::Write>(&self, generics: Option<&GenericTypes>, w: &mut W, t: &syn::Type) -> EmptyValExpectedTy {
                match t {
                        syn::Type::Path(p) => {
                                let resolved = self.resolve_path(&p.path, generics);
                                if self.crate_types.opaques.get(&resolved).is_some() {
                                        write!(w, ".inner.is_null()").unwrap();
-                                       (false, false)
+                                       EmptyValExpectedTy::NonPointer
                                } else {
                                        if let Some(suffix) = self.empty_val_check_suffix_from_path(&resolved) {
                                                write!(w, "{}", suffix).unwrap();
-                                               (false, false) // We may eventually need to allow empty_val_check_suffix_from_path to specify if we need a deref or not
+                                               // 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();
-                                               (true, false)
+                                               EmptyValExpectedTy::OwnedPointer
                                        }
                                }
                        },
@@ -1076,7 +1158,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                if let syn::Expr::Lit(l) = &a.len {
                                        if let syn::Lit::Int(i) = &l.lit {
                                                write!(w, " == [0; {}]", i.base10_digits()).unwrap();
-                                               (false, false)
+                                               EmptyValExpectedTy::NonPointer
                                        } else { unimplemented!(); }
                                } else { unimplemented!(); }
                        },
@@ -1084,7 +1166,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                // Option<[]> always implies that we want to treat len() == 0 differently from
                                // None, so we always map an Option<[]> into a pointer.
                                write!(w, " == std::ptr::null_mut()").unwrap();
-                               (true, true)
+                               EmptyValExpectedTy::ReferenceAsPointer
                        },
                        _ => unimplemented!(),
                }
@@ -1164,23 +1246,24 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                }
 
                                let resolved_path = self.resolve_path(&p.path, generics);
-                               if let Some(c_type) = path_lookup(&resolved_path, is_ref, ptr_for_ref) {
+                               if let Some(aliased_type) = self.crate_types.type_aliases.get(&resolved_path) {
+                                       return self.write_conversion_inline_intern(w, aliased_type, None, is_ref, is_mut, ptr_for_ref, tupleconv, prefix, sliceconv, path_lookup, decl_lookup);
+                               } else if let Some(c_type) = path_lookup(&resolved_path, is_ref, ptr_for_ref) {
                                        write!(w, "{}", c_type).unwrap();
                                } else if self.crate_types.opaques.get(&resolved_path).is_some() {
                                        decl_lookup(w, &DeclType::StructImported, &resolved_path, is_ref, is_mut);
                                } else if self.crate_types.mirrored_enums.get(&resolved_path).is_some() {
                                        decl_lookup(w, &DeclType::MirroredEnum, &resolved_path, is_ref, is_mut);
+                               } else if let Some(t) = self.crate_types.traits.get(&resolved_path) {
+                                       decl_lookup(w, &DeclType::Trait(t), &resolved_path, is_ref, is_mut);
                                } else if let Some(ident) = single_ident_generic_path_to_ident(&p.path) {
-                                       if let Some(t) = self.crate_types.traits.get(&resolved_path) {
-                                               decl_lookup(w, &DeclType::Trait(t), &resolved_path, is_ref, is_mut);
-                                               return;
-                                       } else if let Some(_) = self.imports.get(ident) {
+                                       if let Some(_) = self.imports.get(ident) {
                                                // crate_types lookup has to have succeeded:
                                                panic!("Failed to print inline conversion for {}", ident);
                                        } else if let Some(decl_type) = self.declared.get(ident) {
                                                decl_lookup(w, decl_type, &self.maybe_resolve_ident(ident).unwrap(), is_ref, is_mut);
                                        } else { unimplemented!(); }
-                               }
+                               } else { unimplemented!(); }
                        },
                        syn::Type::Array(a) => {
                                // We assume all arrays contain only [int_literal; X]s.
@@ -1263,6 +1346,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                DeclType::EnumIgnored|DeclType::StructImported if !is_ref =>
                                                        write!(w, "crate::{} {{ inner: Box::into_raw(Box::new(", decl_path).unwrap(),
                                                DeclType::Trait(_) if is_ref => write!(w, "&").unwrap(),
+                                               DeclType::Trait(_) if !is_ref => {},
                                                _ => panic!("{:?}", decl_path),
                                        }
                                });
@@ -1285,6 +1369,13 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                                write!(w, ", is_owned: true }}").unwrap(),
                                        DeclType::EnumIgnored|DeclType::StructImported if !is_ref => write!(w, ")), is_owned: true }}").unwrap(),
                                        DeclType::Trait(_) if is_ref => {},
+                                       DeclType::Trait(_) => {
+                                               // This is used when we're converting a concrete Rust type into a C trait
+                                               // for use when a Rust trait method returns an associated type.
+                                               // Because all of our C traits implement From<RustTypesImplementingTraits>
+                                               // we can just call .into() here and be done.
+                                               write!(w, ".into()").unwrap()
+                                       },
                                        _ => unimplemented!(),
                                });
        }
@@ -1319,7 +1410,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(_) => {},
@@ -1476,6 +1567,9 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                        unimplemented!();
                                }
                                let resolved_path = self.resolve_path(&p.path, generics);
+                               if let Some(aliased_type) = self.crate_types.type_aliases.get(&resolved_path) {
+                                       return self.write_conversion_new_var_intern(w, ident, var, aliased_type, None, is_ref, ptr_for_ref, to_c, path_lookup, container_lookup, var_prefix, var_suffix);
+                               }
                                if self.is_known_container(&resolved_path, is_ref) || self.is_transparent_container(&resolved_path, is_ref) {
                                        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| {
@@ -1644,14 +1738,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();
                                } }
                        }
@@ -1667,20 +1761,20 @@ 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();
-                               self.write_c_type_intern(w, gen, None, false, false, false);
+                               assert!(self.write_c_type_intern(w, gen, None, false, false, false));
                        }
                        writeln!(w, ") -> {} {{", mangled_container).unwrap();
-                       writeln!(w, "\t{} {{", mangled_container).unwrap();
+                       write!(w, "\t{} {{ ", mangled_container).unwrap();
                        for idx in 0..args.len() {
-                               writeln!(w, "\t\t{}: Box::into_raw(Box::new({})),", ('a' as u8 + idx as u8) as char, ('a' as u8 + idx as u8) as char).unwrap();
+                               write!(w, "{}, ", ('a' as u8 + idx as u8) as char).unwrap();
                        }
-                       writeln!(w, "\t}}\n}}\n").unwrap();
+                       writeln!(w, "}}\n}}\n").unwrap();
                } else {
                        writeln!(w, "").unwrap();
                }
        }
 
-       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();
@@ -1690,11 +1784,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) {
@@ -1704,19 +1798,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, &t);
+                                               self.write_rust_type(w, generics, &t);
                                        }
                                } else {
                                        // If we just write out resolved_generic, it may mostly work, however for
@@ -1736,7 +1830,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 {
@@ -1746,7 +1840,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, "{}",
@@ -1761,14 +1855,14 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                        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);
@@ -1949,13 +2043,13 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
                                        if self.is_known_container(&full_path, is_ref) || self.is_transparent_container(&full_path, is_ref) {
                                                return self.write_c_mangled_container_path(w, Self::path_to_generic_args(&p.path), generics, &full_path, is_ref, is_mut, ptr_for_ref);
                                        }
+                                       if let Some(aliased_type) = self.crate_types.type_aliases.get(&full_path).cloned() {
+                                               return self.write_c_type_intern(w, &aliased_type, None, is_ref, is_mut, ptr_for_ref);
+                                       }
                                }
                                self.write_c_path_intern(w, &p.path, generics, is_ref, is_mut, ptr_for_ref)
                        },
                        syn::Type::Reference(r) => {
-                               if let Some(lft) = &r.lifetime {
-                                       if format!("{}", lft.ident) != "static" { return false; }
-                               }
                                self.write_c_type_intern(w, &*r.elem, generics, true, r.mutability.is_some(), ptr_for_ref)
                        },
                        syn::Type::Array(a) => {