Track independent Rust/C++ names on struct fields and fn args
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 6679076..def0447 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -240,7 +240,7 @@
         }
         write!(out, "  ");
         write_type_space(out, &field.ty);
-        writeln!(out, "{};", field.ident);
+        writeln!(out, "{};", field.name.cxx);
     }
 
     writeln!(out);
@@ -755,28 +755,28 @@
         }
         if let Type::RustBox(_) = &arg.ty {
             write_type(out, &arg.ty);
-            write!(out, "::from_raw({})", arg.ident);
+            write!(out, "::from_raw({})", arg.name.cxx);
         } else if let Type::UniquePtr(_) = &arg.ty {
             write_type(out, &arg.ty);
-            write!(out, "({})", arg.ident);
+            write!(out, "({})", arg.name.cxx);
         } else if let Type::Str(_) = arg.ty {
             out.builtin.rust_str_new_unchecked = true;
             write!(
                 out,
                 "::rust::impl<::rust::Str>::new_unchecked({})",
-                arg.ident,
+                arg.name.cxx,
             );
         } else if arg.ty == RustString {
             out.builtin.unsafe_bitcopy = true;
             write!(
                 out,
                 "::rust::String(::rust::unsafe_bitcopy, *{})",
-                arg.ident,
+                arg.name.cxx,
             );
         } else if let Type::RustVec(_) = arg.ty {
             out.builtin.unsafe_bitcopy = true;
             write_type(out, &arg.ty);
-            write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
+            write!(out, "(::rust::unsafe_bitcopy, *{})", arg.name.cxx);
         } else if let Type::SliceRef(slice) = &arg.ty {
             write_type(out, &arg.ty);
             write!(out, "(static_cast<");
@@ -784,12 +784,12 @@
                 write!(out, "const ");
             }
             write_type_space(out, &slice.inner);
-            write!(out, "*>({0}.ptr), {0}.len)", arg.ident);
+            write!(out, "*>({0}.ptr), {0}.len)", arg.name.cxx);
         } else if out.types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
-            write!(out, "::std::move(*{})", arg.ident);
+            write!(out, "::std::move(*{})", arg.name.cxx);
         } else {
-            write!(out, "{}", arg.ident);
+            write!(out, "{}", arg.name.cxx);
         }
     }
     write!(out, ")");
@@ -820,19 +820,14 @@
     writeln!(out, "}}");
     for arg in &efn.args {
         if let Type::Fn(f) = &arg.ty {
-            let var = &arg.ident;
+            let var = &arg.name;
             write_function_pointer_trampoline(out, efn, var, f);
         }
     }
     out.end_block(Block::ExternC);
 }
 
-fn write_function_pointer_trampoline(
-    out: &mut OutFile,
-    efn: &ExternFn,
-    var: &Ident,
-    f: &Signature,
-) {
+fn write_function_pointer_trampoline(out: &mut OutFile, efn: &ExternFn, var: &Pair, f: &Signature) {
     let r_trampoline = mangle::r_trampoline(efn, var, out.types);
     let indirect_call = true;
     write_rust_function_decl_impl(out, &r_trampoline, f, indirect_call);
@@ -928,7 +923,7 @@
             write!(out, ", ");
         }
         write_type_space(out, &arg.ty);
-        write!(out, "{}", arg.ident);
+        write!(out, "{}", arg.name.cxx);
     }
     if indirect_call {
         if !sig.args.is_empty() {
@@ -973,7 +968,7 @@
             out.builtin.manually_drop = true;
             write!(out, "  ::rust::ManuallyDrop<");
             write_type(out, &arg.ty);
-            writeln!(out, "> {}$(::std::move({0}));", arg.ident);
+            writeln!(out, "> {}$(::std::move({0}));", arg.name.cxx);
         }
     }
     write!(out, "  ");
@@ -1037,7 +1032,7 @@
             ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
             _ => {}
         }
-        write!(out, "{}", arg.ident);
+        write!(out, "{}", arg.name.cxx);
         match &arg.ty {
             Type::RustBox(_) => write!(out, ".into_raw()"),
             Type::UniquePtr(_) => write!(out, ".release()"),
@@ -1158,7 +1153,7 @@
     if out.types.needs_indirect_abi(&arg.ty) {
         write!(out, "*");
     }
-    write!(out, "{}", arg.ident);
+    write!(out, "{}", arg.name.cxx);
 }
 
 fn write_type(out: &mut OutFile, ty: &Type) {
diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 5b8f259..3e95ea4 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -104,9 +104,9 @@
     let body = if derive::contains(&strct.derives, Trait::Copy) {
         quote!(*self)
     } else {
-        let fields = strct.fields.iter().map(|field| &field.ident);
+        let fields = strct.fields.iter().map(|field| &field.name.rust);
         let values = strct.fields.iter().map(|field| {
-            let ident = &field.ident;
+            let ident = &field.name.rust;
             let ty = field.ty.to_token_stream();
             let span = ty.into_iter().last().unwrap().span();
             quote_spanned!(span=> &self.#ident)
@@ -128,7 +128,7 @@
 fn struct_debug(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
     let struct_name = ident.to_string();
-    let fields = strct.fields.iter().map(|field| &field.ident);
+    let fields = strct.fields.iter().map(|field| &field.name.rust);
     let field_names = fields.clone().map(Ident::to_string);
 
     quote_spanned! {span=>
@@ -144,7 +144,7 @@
 
 fn struct_default(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
-    let fields = strct.fields.iter().map(|field| &field.ident);
+    let fields = strct.fields.iter().map(|field| &field.name.rust);
 
     quote_spanned! {span=>
         impl ::std::default::Default for #ident {
@@ -161,7 +161,7 @@
 
 fn struct_ord(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
-    let fields = strct.fields.iter().map(|field| &field.ident);
+    let fields = strct.fields.iter().map(|field| &field.name.rust);
 
     quote_spanned! {span=>
         impl ::std::cmp::Ord for #ident {
@@ -186,7 +186,7 @@
             ::std::option::Option::Some(::std::cmp::Ord::cmp(self, other))
         }
     } else {
-        let fields = strct.fields.iter().map(|field| &field.ident);
+        let fields = strct.fields.iter().map(|field| &field.name.rust);
         quote! {
             #(
                 match ::std::cmp::PartialOrd::partial_cmp(&self.#fields, &other.#fields) {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 40ed5e2..d67361a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -395,7 +395,7 @@
         quote!(_: #receiver_type)
     });
     let args = efn.args.iter().map(|arg| {
-        let ident = &arg.ident;
+        let ident = &arg.name.rust;
         let ty = expand_extern_type(&arg.ty, types, true);
         if arg.ty == RustString {
             quote!(#ident: *const #ty)
@@ -461,7 +461,7 @@
         .iter()
         .map(|receiver| receiver.var.to_token_stream());
     let arg_vars = efn.args.iter().map(|arg| {
-        let var = &arg.ident;
+        let var = &arg.name.rust;
         match &arg.ty {
             Type::Ident(ident) if ident.rust == RustString => {
                 quote!(#var.as_mut_ptr() as *const ::cxx::private::RustString)
@@ -503,7 +503,7 @@
         .iter()
         .filter_map(|arg| {
             if let Type::Fn(f) = &arg.ty {
-                let var = &arg.ident;
+                let var = &arg.name;
                 Some(expand_function_pointer_trampoline(efn, var, f, types))
             } else {
                 None
@@ -515,7 +515,7 @@
         .iter()
         .filter(|arg| types.needs_indirect_abi(&arg.ty))
         .map(|arg| {
-            let var = &arg.ident;
+            let var = &arg.name.rust;
             // These are arguments for which C++ has taken ownership of the data
             // behind the mut reference it received.
             quote! {
@@ -632,14 +632,14 @@
 
 fn expand_function_pointer_trampoline(
     efn: &ExternFn,
-    var: &Ident,
+    var: &Pair,
     sig: &Signature,
     types: &Types,
 ) -> TokenStream {
     let c_trampoline = mangle::c_trampoline(efn, var, types);
     let r_trampoline = mangle::r_trampoline(efn, var, types);
     let local_name = parse_quote!(__);
-    let catch_unwind_label = format!("::{}::{}", efn.name.rust, var);
+    let catch_unwind_label = format!("::{}::{}", efn.name.rust, var.rust);
     let shim = expand_rust_function_shim_impl(
         sig,
         types,
@@ -648,6 +648,7 @@
         catch_unwind_label,
         None,
     );
+    let var = &var.rust;
 
     quote! {
         let #var = ::cxx::private::FatFunction {
@@ -792,7 +793,7 @@
         quote!(#receiver_var: #receiver_type)
     });
     let args = sig.args.iter().map(|arg| {
-        let ident = &arg.ident;
+        let ident = &arg.name.rust;
         let ty = expand_extern_type(&arg.ty, types, false);
         if types.needs_indirect_abi(&arg.ty) {
             quote!(#ident: *mut #ty)
@@ -803,7 +804,7 @@
     let all_args = receiver.into_iter().chain(args);
 
     let arg_vars = sig.args.iter().map(|arg| {
-        let ident = &arg.ident;
+        let ident = &arg.name.rust;
         match &arg.ty {
             Type::Ident(i) if i.rust == RustString => {
                 quote!(::std::mem::take((*#ident).as_mut_string()))
@@ -969,7 +970,7 @@
         expand_return_type(&sig.ret)
     };
 
-    let arg_vars = sig.args.iter().map(|arg| &arg.ident);
+    let arg_vars = sig.args.iter().map(|arg| &arg.name.rust);
     let vars = receiver_var.iter().chain(arg_vars);
 
     let span = invoke.span();
diff --git a/syntax/ident.rs b/syntax/ident.rs
index 47aae14..076fe92 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -26,7 +26,7 @@
             Api::Struct(strct) => {
                 check_ident(cx, &strct.name);
                 for field in &strct.fields {
-                    check(cx, &field.ident);
+                    check_ident(cx, &field.name);
                 }
             }
             Api::Enum(enm) => {
@@ -41,7 +41,7 @@
             Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                 check(cx, &efn.name.rust);
                 for arg in &efn.args {
-                    check(cx, &arg.ident);
+                    check_ident(cx, &arg.name);
                 }
             }
             Api::TypeAlias(alias) => {
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 8762652..ae4a77d 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -301,14 +301,14 @@
                     doc: _,
                     attrs: _,
                     visibility: _,
-                    ident: _,
+                    name: _,
                     ty,
                 } = arg;
                 let Var {
                     doc: _,
                     attrs: _,
                     visibility: _,
-                    ident: _,
+                    name: _,
                     ty: ty2,
                 } = arg2;
                 ty == ty2
@@ -336,7 +336,7 @@
                 doc: _,
                 attrs: _,
                 visibility: _,
-                ident: _,
+                name: _,
                 ty,
             } = arg;
             ty.hash(state);
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 0d395e3..71a60be 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -1,6 +1,5 @@
 use crate::syntax::symbol::{self, Symbol};
 use crate::syntax::{ExternFn, Pair, Types};
-use proc_macro2::Ident;
 
 const CXXBRIDGE: &str = "cxxbridge1";
 
@@ -36,11 +35,11 @@
 }
 
 // The C half of a function pointer trampoline.
-pub fn c_trampoline(efn: &ExternFn, var: &Ident, types: &Types) -> Symbol {
-    join!(extern_fn(efn, types), var, 0)
+pub fn c_trampoline(efn: &ExternFn, var: &Pair, types: &Types) -> Symbol {
+    join!(extern_fn(efn, types), var.rust, 0)
 }
 
 // The Rust half of a function pointer trampoline.
-pub fn r_trampoline(efn: &ExternFn, var: &Ident, types: &Types) -> Symbol {
-    join!(extern_fn(efn, types), var, 1)
+pub fn r_trampoline(efn: &ExternFn, var: &Pair, types: &Types) -> Symbol {
+    join!(extern_fn(efn, types), var.rust, 1)
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 4298995..9b4a101 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -167,7 +167,7 @@
     pub doc: Doc,
     pub attrs: OtherAttrs,
     pub visibility: Token![pub],
-    pub ident: Ident,
+    pub name: Pair,
     pub ty: Type,
 }
 
diff --git a/syntax/parse.rs b/syntax/parse.rs
index b36bcbf..fd558dc 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -116,11 +116,12 @@
             }
         };
         let visibility = visibility_pub(&field.vis, &ident);
+        let name = pair(Namespace::default(), &ident, None, None);
         fields.push(Var {
             doc,
             attrs,
             visibility,
-            ident,
+            name,
             ty,
         });
     }
@@ -541,11 +542,12 @@
                     let doc = Doc::new();
                     let attrs = OtherAttrs::none();
                     let visibility = Token![pub](ident.span());
+                    let name = pair(Namespace::default(), &ident, None, None);
                     args.push_value(Var {
                         doc,
                         attrs,
                         visibility,
-                        ident,
+                        name,
                         ty,
                     });
                     if let Some(comma) = comma {
@@ -1177,11 +1179,12 @@
             let doc = Doc::new();
             let attrs = OtherAttrs::none();
             let visibility = Token![pub](ident.span());
+            let name = pair(Namespace::default(), &ident, None, None);
             Ok(Var {
                 doc,
                 attrs,
                 visibility,
-                ident,
+                name,
                 ty,
             })
         })
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index df0b702..aec21ae 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -41,11 +41,11 @@
             doc: _,
             attrs: _,
             visibility: _,
-            ident,
+            name,
             ty,
         } = self;
-        ident.to_tokens(tokens);
-        Token![:](ident.span()).to_tokens(tokens);
+        name.rust.to_tokens(tokens);
+        Token![:](name.rust.span()).to_tokens(tokens);
         ty.to_tokens(tokens);
     }
 }