Record lifetimes associated with generic type instantiation
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 5e2473a..73a4b8c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -657,7 +657,7 @@
         write!(
             out,
             "{} &self",
-            out.types.resolve(&receiver.ty).to_fully_qualified(),
+            out.types.resolve(&receiver.ty).name.to_fully_qualified(),
         );
     }
     for (i, arg) in efn.args.iter().enumerate() {
@@ -687,7 +687,7 @@
         Some(receiver) => write!(
             out,
             "({}::*{}$)(",
-            out.types.resolve(&receiver.ty).to_fully_qualified(),
+            out.types.resolve(&receiver.ty).name.to_fully_qualified(),
             efn.name.rust,
         ),
     }
@@ -709,7 +709,7 @@
         Some(receiver) => write!(
             out,
             "&{}::{}",
-            out.types.resolve(&receiver.ty).to_fully_qualified(),
+            out.types.resolve(&receiver.ty).name.to_fully_qualified(),
             efn.name.cxx,
         ),
     }
@@ -868,7 +868,7 @@
         write!(
             out,
             "{} &self",
-            out.types.resolve(&receiver.ty).to_fully_qualified(),
+            out.types.resolve(&receiver.ty).name.to_fully_qualified(),
         );
         needs_comma = true;
     }
@@ -903,7 +903,11 @@
     }
     let local_name = match &efn.sig.receiver {
         None => efn.name.cxx.to_string(),
-        Some(receiver) => format!("{}::{}", out.types.resolve(&receiver.ty).cxx, efn.name.cxx),
+        Some(receiver) => format!(
+            "{}::{}",
+            out.types.resolve(&receiver.ty).name.cxx,
+            efn.name.cxx,
+        ),
     };
     let invoke = mangle::extern_fn(efn, out.types);
     let indirect_call = false;
@@ -1160,7 +1164,11 @@
     match ty {
         Type::Ident(ident) => match Atom::from(&ident.rust) {
             Some(atom) => write_atom(out, atom),
-            None => write!(out, "{}", out.types.resolve(ident).to_fully_qualified()),
+            None => write!(
+                out,
+                "{}",
+                out.types.resolve(ident).name.to_fully_qualified(),
+            ),
         },
         Type::RustBox(ty) => {
             write!(out, "::rust::Box<");
@@ -1290,7 +1298,7 @@
 
 impl ToTypename for Ident {
     fn to_typename(&self, types: &Types) -> String {
-        types.resolve(self).to_fully_qualified()
+        types.resolve(self).name.to_fully_qualified()
     }
 }
 
@@ -1311,7 +1319,7 @@
 
 impl ToMangled for Ident {
     fn to_mangled(&self, types: &Types) -> Symbol {
-        types.resolve(self).to_symbol()
+        types.resolve(self).name.to_symbol()
     }
 }
 
@@ -1360,8 +1368,8 @@
 
 fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     let resolve = out.types.resolve(ident);
-    let inner = resolve.to_fully_qualified();
-    let instance = resolve.to_symbol();
+    let inner = resolve.name.to_fully_qualified();
+    let instance = resolve.name.to_symbol();
 
     writeln!(
         out,
@@ -1425,8 +1433,8 @@
 
 fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     let resolve = out.types.resolve(ident);
-    let inner = resolve.to_fully_qualified();
-    let instance = resolve.to_symbol();
+    let inner = resolve.name.to_fully_qualified();
+    let instance = resolve.name.to_symbol();
 
     writeln!(out, "template <>");
     begin_function_definition(out);
@@ -1567,7 +1575,7 @@
     if conditional_delete {
         out.builtin.is_complete = true;
         let definition = match ty {
-            UniquePtr::Ident(ty) => &out.types.resolve(ty).cxx,
+            UniquePtr::Ident(ty) => &out.types.resolve(ty).name.cxx,
             UniquePtr::CxxVector(_) => unreachable!(),
         };
         writeln!(
@@ -1650,8 +1658,8 @@
 
 fn write_shared_ptr(out: &mut OutFile, ident: &Ident) {
     let resolve = out.types.resolve(ident);
-    let inner = resolve.to_fully_qualified();
-    let instance = resolve.to_symbol();
+    let inner = resolve.name.to_fully_qualified();
+    let instance = resolve.name.to_symbol();
 
     out.include.new = true;
     out.include.utility = true;
@@ -1722,8 +1730,8 @@
 
 fn write_weak_ptr(out: &mut OutFile, ident: &Ident) {
     let resolve = out.types.resolve(ident);
-    let inner = resolve.to_fully_qualified();
-    let instance = resolve.to_symbol();
+    let inner = resolve.name.to_fully_qualified();
+    let instance = resolve.name.to_symbol();
 
     out.include.new = true;
     out.include.utility = true;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index d67361a..8149d5d 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1038,7 +1038,7 @@
 
 fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
     let resolve = types.resolve(ident);
-    let link_prefix = format!("cxxbridge1$box${}$", resolve.to_symbol());
+    let link_prefix = format!("cxxbridge1$box${}$", resolve.name.to_symbol());
     let link_alloc = format!("{}alloc", link_prefix);
     let link_dealloc = format!("{}dealloc", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
@@ -1076,7 +1076,7 @@
 
 fn expand_rust_vec(elem: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
     let resolve = types.resolve(elem);
-    let link_prefix = format!("cxxbridge1$rust_vec${}$", resolve.to_symbol());
+    let link_prefix = format!("cxxbridge1$rust_vec${}$", resolve.name.to_symbol());
     let link_new = format!("{}new", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
@@ -1143,7 +1143,7 @@
 fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
     let name = ident.to_string();
     let resolve = types.resolve(ident);
-    let prefix = format!("cxxbridge1$unique_ptr${}$", resolve.to_symbol());
+    let prefix = format!("cxxbridge1$unique_ptr${}$", resolve.name.to_symbol());
     let link_null = format!("{}null", prefix);
     let link_uninit = format!("{}uninit", prefix);
     let link_raw = format!("{}raw", prefix);
@@ -1225,7 +1225,7 @@
 fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
     let name = ident.to_string();
     let resolve = types.resolve(ident);
-    let prefix = format!("cxxbridge1$shared_ptr${}$", resolve.to_symbol());
+    let prefix = format!("cxxbridge1$shared_ptr${}$", resolve.name.to_symbol());
     let link_null = format!("{}null", prefix);
     let link_uninit = format!("{}uninit", prefix);
     let link_clone = format!("{}clone", prefix);
@@ -1293,7 +1293,7 @@
 fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
     let name = ident.to_string();
     let resolve = types.resolve(ident);
-    let prefix = format!("cxxbridge1$weak_ptr${}$", resolve.to_symbol());
+    let prefix = format!("cxxbridge1$weak_ptr${}$", resolve.name.to_symbol());
     let link_null = format!("{}null", prefix);
     let link_clone = format!("{}clone", prefix);
     let link_downgrade = format!("{}downgrade", prefix);
@@ -1350,10 +1350,13 @@
 fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) -> TokenStream {
     let name = elem.to_string();
     let resolve = types.resolve(elem);
-    let prefix = format!("cxxbridge1$std$vector${}$", resolve.to_symbol());
+    let prefix = format!("cxxbridge1$std$vector${}$", resolve.name.to_symbol());
     let link_size = format!("{}size", prefix);
     let link_get_unchecked = format!("{}get_unchecked", prefix);
-    let unique_ptr_prefix = format!("cxxbridge1$unique_ptr$std$vector${}$", resolve.to_symbol());
+    let unique_ptr_prefix = format!(
+        "cxxbridge1$unique_ptr$std$vector${}$",
+        resolve.name.to_symbol(),
+    );
     let link_unique_ptr_null = format!("{}null", unique_ptr_prefix);
     let link_unique_ptr_raw = format!("{}raw", unique_ptr_prefix);
     let link_unique_ptr_get = format!("{}get", unique_ptr_prefix);
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 71a60be..901830a 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -16,7 +16,7 @@
             join!(
                 efn.name.namespace,
                 CXXBRIDGE,
-                receiver_ident.cxx,
+                receiver_ident.name.cxx,
                 efn.name.rust,
             )
         }
diff --git a/syntax/resolve.rs b/syntax/resolve.rs
index 5bb1535..08fcf16 100644
--- a/syntax/resolve.rs
+++ b/syntax/resolve.rs
@@ -1,9 +1,16 @@
-use crate::syntax::{NamedType, Pair, Types};
+use crate::syntax::{Lifetimes, NamedType, Pair, Types};
 use proc_macro2::Ident;
 
+#[derive(Copy, Clone)]
+pub struct Resolution<'a> {
+    pub name: &'a Pair,
+    pub generics: &'a Lifetimes,
+}
+
 impl<'a> Types<'a> {
-    pub fn resolve(&self, ident: &impl UnresolvedName) -> &Pair {
-        self.resolutions
+    pub fn resolve(&self, ident: &impl UnresolvedName) -> Resolution<'a> {
+        *self
+            .resolutions
             .get(ident.ident())
             .expect("Unable to resolve type")
     }
diff --git a/syntax/types.rs b/syntax/types.rs
index 0eb4293..7bf2baf 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -2,9 +2,12 @@
 use crate::syntax::instantiate::ImplKey;
 use crate::syntax::map::{OrderedMap, UnorderedMap};
 use crate::syntax::report::Errors;
+use crate::syntax::resolve::Resolution;
 use crate::syntax::set::{OrderedSet, UnorderedSet};
 use crate::syntax::trivial::{self, TrivialReason};
-use crate::syntax::{toposort, Api, Atom, Enum, ExternType, Impl, Pair, Struct, Type, TypeAlias};
+use crate::syntax::{
+    toposort, Api, Atom, Enum, ExternType, Impl, Lifetimes, Pair, Struct, Type, TypeAlias,
+};
 use proc_macro2::Ident;
 use quote::ToTokens;
 
@@ -18,7 +21,7 @@
     pub untrusted: UnorderedMap<&'a Ident, &'a ExternType>,
     pub required_trivial: UnorderedMap<&'a Ident, Vec<TrivialReason<'a>>>,
     pub impls: OrderedMap<ImplKey<'a>, Option<&'a Impl>>,
-    pub resolutions: UnorderedMap<&'a Ident, &'a Pair>,
+    pub resolutions: UnorderedMap<&'a Ident, Resolution<'a>>,
     pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
     pub toposorted_structs: Vec<&'a Struct>,
 }
@@ -61,8 +64,8 @@
             }
         }
 
-        let mut add_resolution = |pair: &'a Pair| {
-            resolutions.insert(&pair.rust, pair);
+        let mut add_resolution = |name: &'a Pair, generics: &'a Lifetimes| {
+            resolutions.insert(&name.rust, Resolution { name, generics });
         };
 
         let mut type_names = UnorderedSet::new();
@@ -92,7 +95,7 @@
                     for field in &strct.fields {
                         visit(&mut all, &field.ty);
                     }
-                    add_resolution(&strct.name);
+                    add_resolution(&strct.name, &strct.generics);
                 }
                 Api::Enum(enm) => {
                     all.insert(&enm.repr_type);
@@ -108,7 +111,7 @@
                         duplicate_name(cx, enm, ident);
                     }
                     enums.insert(ident, enm);
-                    add_resolution(&enm.name);
+                    add_resolution(&enm.name, &enm.generics);
                 }
                 Api::CxxType(ety) => {
                     let ident = &ety.name.rust;
@@ -125,7 +128,7 @@
                     if !ety.trusted {
                         untrusted.insert(ident, ety);
                     }
-                    add_resolution(&ety.name);
+                    add_resolution(&ety.name, &ety.generics);
                 }
                 Api::RustType(ety) => {
                     let ident = &ety.name.rust;
@@ -133,7 +136,7 @@
                         duplicate_name(cx, ety, ident);
                     }
                     rust.insert(ident);
-                    add_resolution(&ety.name);
+                    add_resolution(&ety.name, &ety.generics);
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                     // Note: duplication of the C++ name is fine because C++ has
@@ -155,7 +158,7 @@
                     }
                     cxx.insert(ident);
                     aliases.insert(ident, alias);
-                    add_resolution(&alias.name);
+                    add_resolution(&alias.name, &alias.generics);
                 }
                 Api::Impl(imp) => {
                     visit(&mut all, &imp.ty);