Move CppName's namespace into Pair
diff --git a/gen/src/namespace.rs b/gen/src/namespace.rs
index a8b049f..7343875 100644
--- a/gen/src/namespace.rs
+++ b/gen/src/namespace.rs
@@ -4,10 +4,10 @@
 impl Api {
     pub fn namespace(&self) -> &Namespace {
         match self {
-            Api::CxxFunction(efn) | Api::RustFunction(efn) => &efn.ident.cxx.namespace,
-            Api::CxxType(ety) | Api::RustType(ety) => &ety.ident.cxx.namespace,
-            Api::Enum(enm) => &enm.ident.cxx.namespace,
-            Api::Struct(strct) => &strct.ident.cxx.namespace,
+            Api::CxxFunction(efn) | Api::RustFunction(efn) => &efn.ident.namespace,
+            Api::CxxType(ety) | Api::RustType(ety) => &ety.ident.namespace,
+            Api::Enum(enm) => &enm.ident.namespace,
+            Api::Struct(strct) => &strct.ident.namespace,
             Api::Impl(_) | Api::Include(_) | Api::TypeAlias(_) => Default::default(),
         }
     }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 1cd6d07..7c16e81 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -5,8 +5,8 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    mangle, Api, CppName, Enum, ExternFn, ExternType, ResolvableName, Signature, Struct, Type,
-    Types, Var,
+    mangle, Api, Enum, ExternFn, ExternType, Pair, ResolvableName, Signature, Struct, Type, Types,
+    Var,
 };
 use proc_macro2::Ident;
 use std::collections::HashMap;
@@ -47,10 +47,10 @@
         for api in apis {
             write!(out, "{:1$}", "", indent);
             match api {
-                Api::Struct(strct) => write_struct_decl(out, &strct.ident.cxx.ident),
+                Api::Struct(strct) => write_struct_decl(out, &strct.ident.cxx),
                 Api::Enum(enm) => write_enum_decl(out, enm),
-                Api::CxxType(ety) => write_struct_using(out, &ety.ident.cxx),
-                Api::RustType(ety) => write_struct_decl(out, &ety.ident.cxx.ident),
+                Api::CxxType(ety) => write_struct_using(out, &ety.ident),
+                Api::RustType(ety) => write_struct_decl(out, &ety.ident.cxx),
                 _ => unreachable!(),
             }
         }
@@ -106,7 +106,7 @@
     for api in apis {
         if let Api::TypeAlias(ety) = api {
             if out.types.required_trivial.contains_key(&ety.ident.rust) {
-                check_trivial_extern_type(out, &ety.ident.cxx)
+                check_trivial_extern_type(out, &ety.ident)
             }
         }
     }
@@ -193,14 +193,14 @@
 }
 
 fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
-    out.set_namespace(&strct.ident.cxx.namespace);
-    let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.ident.cxx.to_symbol());
+    out.set_namespace(&strct.ident.namespace);
+    let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.ident.to_symbol());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
     for line in strct.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
-    writeln!(out, "struct {} final {{", strct.ident.cxx.ident);
+    writeln!(out, "struct {} final {{", strct.ident.cxx);
     for field in &strct.fields {
         write!(out, "  ");
         write_type_space(out, &field.ty);
@@ -215,18 +215,13 @@
 }
 
 fn write_enum_decl(out: &mut OutFile, enm: &Enum) {
-    write!(out, "enum class {} : ", enm.ident.cxx.ident);
+    write!(out, "enum class {} : ", enm.ident.cxx);
     write_atom(out, enm.repr);
     writeln!(out, ";");
 }
 
-fn write_struct_using(out: &mut OutFile, ident: &CppName) {
-    writeln!(
-        out,
-        "using {} = {};",
-        ident.ident,
-        ident.to_fully_qualified()
-    );
+fn write_struct_using(out: &mut OutFile, ident: &Pair) {
+    writeln!(out, "using {} = {};", ident.cxx, ident.to_fully_qualified());
 }
 
 fn write_struct_with_methods<'a>(
@@ -234,24 +229,24 @@
     ety: &'a ExternType,
     methods: &[&ExternFn],
 ) {
-    out.set_namespace(&ety.ident.cxx.namespace);
-    let guard = format!("CXXBRIDGE05_STRUCT_{}", ety.ident.cxx.to_symbol());
+    out.set_namespace(&ety.ident.namespace);
+    let guard = format!("CXXBRIDGE05_STRUCT_{}", ety.ident.to_symbol());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
     for line in ety.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
-    writeln!(out, "struct {} final {{", ety.ident.cxx.ident);
-    writeln!(out, "  {}() = delete;", ety.ident.cxx.ident);
+    writeln!(out, "struct {} final {{", ety.ident.cxx);
+    writeln!(out, "  {}() = delete;", ety.ident.cxx);
     writeln!(
         out,
         "  {}(const {} &) = delete;",
-        ety.ident.cxx.ident, ety.ident.cxx.ident
+        ety.ident.cxx, ety.ident.cxx,
     );
     for method in methods {
         write!(out, "  ");
         let sig = &method.sig;
-        let local_name = method.ident.cxx.ident.to_string();
+        let local_name = method.ident.cxx.to_string();
         write_rust_function_shim_decl(out, &local_name, sig, false);
         writeln!(out, ";");
     }
@@ -260,14 +255,14 @@
 }
 
 fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
-    out.set_namespace(&enm.ident.cxx.namespace);
-    let guard = format!("CXXBRIDGE05_ENUM_{}", enm.ident.cxx.to_symbol());
+    out.set_namespace(&enm.ident.namespace);
+    let guard = format!("CXXBRIDGE05_ENUM_{}", enm.ident.to_symbol());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
     for line in enm.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
-    write!(out, "enum class {} : ", enm.ident.cxx.ident);
+    write!(out, "enum class {} : ", enm.ident.cxx);
     write_atom(out, enm.repr);
     writeln!(out, " {{");
     for variant in &enm.variants {
@@ -278,12 +273,8 @@
 }
 
 fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
-    out.set_namespace(&enm.ident.cxx.namespace);
-    write!(
-        out,
-        "static_assert(sizeof({}) == sizeof(",
-        enm.ident.cxx.ident
-    );
+    out.set_namespace(&enm.ident.namespace);
+    write!(out, "static_assert(sizeof({}) == sizeof(", enm.ident.cxx);
     write_atom(out, enm.repr);
     writeln!(out, "), \"incorrect size\");");
     for variant in &enm.variants {
@@ -292,12 +283,12 @@
         writeln!(
             out,
             ">({}::{}) == {}, \"disagrees with the value in #[cxx::bridge]\");",
-            enm.ident.cxx.ident, variant.ident, variant.discriminant,
+            enm.ident.cxx, variant.ident, variant.discriminant,
         );
     }
 }
 
-fn check_trivial_extern_type(out: &mut OutFile, id: &CppName) {
+fn check_trivial_extern_type(out: &mut OutFile, id: &Pair) {
     // NOTE: The following two static assertions are just nice-to-have and not
     // necessary for soundness. That's because triviality is always declared by
     // the user in the form of an unsafe impl of cxx::ExternType:
@@ -340,7 +331,7 @@
 
 fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     out.next_section();
-    out.set_namespace(&efn.ident.cxx.namespace);
+    out.set_namespace(&efn.ident.namespace);
     out.begin_block(Block::ExternC);
     if let Some(annotation) = &out.opt.cxx_impl_annotations {
         write!(out, "{} ", annotation);
@@ -360,7 +351,7 @@
         write!(
             out,
             "{} &self",
-            out.types.resolve(&receiver.ty).to_fully_qualified()
+            out.types.resolve(&receiver.ty).to_fully_qualified(),
         );
     }
     for (i, arg) in efn.args.iter().enumerate() {
@@ -391,7 +382,7 @@
             out,
             "({}::*{}$)(",
             out.types.resolve(&receiver.ty).to_fully_qualified(),
-            efn.ident.rust
+            efn.ident.rust,
         ),
     }
     for (i, arg) in efn.args.iter().enumerate() {
@@ -408,12 +399,12 @@
     }
     write!(out, " = ");
     match &efn.receiver {
-        None => write!(out, "{}", efn.ident.cxx.to_fully_qualified()),
+        None => write!(out, "{}", efn.ident.to_fully_qualified()),
         Some(receiver) => write!(
             out,
             "&{}::{}",
             out.types.resolve(&receiver.ty).to_fully_qualified(),
-            efn.ident.cxx.ident
+            efn.ident.cxx,
         ),
     }
     writeln!(out, ";");
@@ -542,7 +533,7 @@
 }
 
 fn write_rust_function_decl<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
-    out.set_namespace(&efn.ident.cxx.namespace);
+    out.set_namespace(&efn.ident.namespace);
     out.begin_block(Block::ExternC);
     let link_name = mangle::extern_fn(efn, out.types);
     let indirect_call = false;
@@ -572,7 +563,7 @@
         write!(
             out,
             "{} &self",
-            out.types.resolve(&receiver.ty).to_fully_qualified()
+            out.types.resolve(&receiver.ty).to_fully_qualified(),
         );
         needs_comma = true;
     }
@@ -601,17 +592,13 @@
 }
 
 fn write_rust_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
-    out.set_namespace(&efn.ident.cxx.namespace);
+    out.set_namespace(&efn.ident.namespace);
     for line in efn.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
     let local_name = match &efn.sig.receiver {
-        None => efn.ident.cxx.ident.to_string(),
-        Some(receiver) => format!(
-            "{}::{}",
-            out.types.resolve(&receiver.ty).ident,
-            efn.ident.cxx.ident
-        ),
+        None => efn.ident.cxx.to_string(),
+        Some(receiver) => format!("{}::{}", out.types.resolve(&receiver.ty).cxx, efn.ident.cxx),
     };
     let invoke = mangle::extern_fn(efn, out.types);
     let indirect_call = false;
@@ -1041,7 +1028,7 @@
     out.end_block(Block::Namespace("rust"));
 }
 
-fn write_rust_box_extern(out: &mut OutFile, ident: &CppName) {
+fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
     let inner = ident.to_fully_qualified();
     let instance = ident.to_symbol();
 
@@ -1095,7 +1082,7 @@
     writeln!(out, "#endif // CXXBRIDGE05_RUST_VEC_{}", instance);
 }
 
-fn write_rust_box_impl(out: &mut OutFile, ident: &CppName) {
+fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
     let inner = ident.to_fully_qualified();
     let instance = ident.to_symbol();
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index b25d830..026ec43 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -4,7 +4,7 @@
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, CppName, Enum, ExternFn, ExternType, Impl, ResolvableName, Signature,
+    self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Signature,
     Struct, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
@@ -125,11 +125,10 @@
 }
 
 fn expand_struct(strct: &Struct) -> TokenStream {
-    let ident = &strct.ident.rust;
-    let cxx_ident = &strct.ident.cxx;
+    let ident = &strct.ident;
     let doc = &strct.doc;
     let derives = DeriveAttribute(&strct.derives);
-    let type_id = type_id(cxx_ident);
+    let type_id = type_id(&strct.ident);
     let fields = strct.fields.iter().map(|field| {
         // This span on the pub makes "private type in public interface" errors
         // appear in the right place.
@@ -153,11 +152,10 @@
 }
 
 fn expand_enum(enm: &Enum) -> TokenStream {
-    let ident = &enm.ident.rust;
-    let cxx_ident = &enm.ident.cxx;
+    let ident = &enm.ident;
     let doc = &enm.doc;
     let repr = enm.repr;
-    let type_id = type_id(cxx_ident);
+    let type_id = type_id(&enm.ident);
     let variants = enm.variants.iter().map(|variant| {
         let variant_ident = &variant.ident;
         let discriminant = &variant.discriminant;
@@ -187,10 +185,9 @@
 }
 
 fn expand_cxx_type(ety: &ExternType) -> TokenStream {
-    let ident = &ety.ident.rust;
-    let cxx_ident = &ety.ident.cxx;
+    let ident = &ety.ident;
     let doc = &ety.doc;
-    let type_id = type_id(&cxx_ident);
+    let type_id = type_id(&ety.ident);
 
     quote! {
         #doc
@@ -423,7 +420,7 @@
     if unsafety.is_none() {
         dispatch = quote!(unsafe { #dispatch });
     }
-    let ident = &efn.ident.rust;
+    let ident = &efn.ident;
     let function_shim = quote! {
         #doc
         pub #unsafety fn #ident(#(#all_args,)*) #ret {
@@ -688,7 +685,7 @@
 
 fn expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenStream {
     let ident = &alias.ident;
-    let type_id = type_id(&ident.cxx);
+    let type_id = type_id(ident);
     let begin_span = alias.type_token.span;
     let end_span = alias.semi_token.span;
     let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_type::<);
@@ -708,8 +705,8 @@
     verify
 }
 
-fn type_id(ident: &CppName) -> TokenStream {
-    let path = ident.to_fully_qualified();
+fn type_id(name: &Pair) -> TokenStream {
+    let path = name.to_fully_qualified();
     quote! {
         ::cxx::type_id!(#path)
     }
diff --git a/syntax/ident.rs b/syntax/ident.rs
index 03c4380..bb2fe46 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -1,5 +1,5 @@
 use crate::syntax::check::Check;
-use crate::syntax::{error, Api, CppName};
+use crate::syntax::{error, Api, Pair};
 use proc_macro2::Ident;
 
 fn check(cx: &mut Check, ident: &Ident) {
@@ -12,11 +12,11 @@
     }
 }
 
-fn check_ident(cx: &mut Check, ident: &CppName) {
-    for segment in &ident.namespace {
+fn check_ident(cx: &mut Check, name: &Pair) {
+    for segment in &name.namespace {
         check(cx, segment);
     }
-    check(cx, &ident.ident);
+    check(cx, &name.cxx);
 }
 
 pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
@@ -24,19 +24,19 @@
         match api {
             Api::Include(_) | Api::Impl(_) => {}
             Api::Struct(strct) => {
-                check_ident(cx, &strct.ident.cxx);
+                check_ident(cx, &strct.ident);
                 for field in &strct.fields {
                     check(cx, &field.ident);
                 }
             }
             Api::Enum(enm) => {
-                check_ident(cx, &enm.ident.cxx);
+                check_ident(cx, &enm.ident);
                 for variant in &enm.variants {
                     check(cx, &variant.ident);
                 }
             }
             Api::CxxType(ety) | Api::RustType(ety) => {
-                check_ident(cx, &ety.ident.cxx);
+                check_ident(cx, &ety.ident);
             }
             Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                 check(cx, &efn.ident.rust);
@@ -45,7 +45,7 @@
                 }
             }
             Api::TypeAlias(alias) => {
-                check_ident(cx, &alias.ident.cxx);
+                check_ident(cx, &alias.ident);
             }
         }
     }
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index d1f3adc..55ffca5 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -15,13 +15,13 @@
         Some(receiver) => {
             let receiver_ident = types.resolve(&receiver.ty);
             join!(
-                efn.ident.cxx.namespace,
+                efn.ident.namespace,
                 CXXBRIDGE,
-                receiver_ident.ident,
+                receiver_ident.cxx,
                 efn.ident.rust
             )
         }
-        None => join!(efn.ident.cxx.namespace, CXXBRIDGE, efn.ident.rust),
+        None => join!(efn.ident.namespace, CXXBRIDGE, efn.ident.rust),
     }
 }
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index b12d72b..6684b6a 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -188,17 +188,9 @@
 // qualified C++ name.
 #[derive(Clone)]
 pub struct Pair {
-    pub cxx: CppName,
-    pub rust: Ident,
-}
-
-// A C++ identifier in a particular namespace. It is intentional that this does
-// not impl Display, because we want to force users actively to decide whether
-// to output it as a qualified name or as an unqualfied name.
-#[derive(Clone)]
-pub struct CppName {
     pub namespace: Namespace,
-    pub ident: Ident,
+    pub cxx: Ident,
+    pub rust: Ident,
 }
 
 // Wrapper for a type which needs to be resolved before it can be printed in
diff --git a/syntax/names.rs b/syntax/names.rs
index ee010a9..25ae9f4 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -1,29 +1,51 @@
-use crate::syntax::{CppName, Namespace, Pair, ResolvableName, Symbol, Types};
+use crate::syntax::{Namespace, Pair, ResolvableName, Symbol, Types};
 use proc_macro2::{Ident, Span};
+use std::iter;
 use syn::Token;
 
 impl Pair {
-    /// Use this constructor when the item can't have a different
-    /// name in Rust and C++.
+    // Use this constructor when the item can't have a different name in Rust
+    // and C++.
     pub fn new(namespace: Namespace, ident: Ident) -> Self {
         Self {
-            rust: ident.clone(),
-            cxx: CppName::new(namespace, ident),
+            namespace,
+            cxx: ident.clone(),
+            rust: ident,
         }
     }
 
-    /// Use this constructor when attributes such as #[rust_name]
-    /// can be used to potentially give a different name in Rust vs C++.
+    // Use this constructor when attributes such as #[rust_name] can be used to
+    // potentially give a different name in Rust vs C++.
     pub fn new_from_differing_names(
         namespace: Namespace,
         cxx_ident: Ident,
         rust_ident: Ident,
     ) -> Self {
         Self {
+            namespace,
+            cxx: cxx_ident,
             rust: rust_ident,
-            cxx: CppName::new(namespace, cxx_ident),
         }
     }
+
+    pub fn to_symbol(&self) -> Symbol {
+        Symbol::from_idents(self.iter_all_segments())
+    }
+
+    pub fn to_fully_qualified(&self) -> String {
+        format!("::{}", self.join("::"))
+    }
+
+    fn iter_all_segments(&self) -> impl Iterator<Item = &Ident> {
+        self.namespace.iter().chain(iter::once(&self.cxx))
+    }
+
+    fn join(&self, sep: &str) -> String {
+        self.iter_all_segments()
+            .map(|s| s.to_string())
+            .collect::<Vec<_>>()
+            .join(sep)
+    }
 }
 
 impl ResolvableName {
@@ -49,28 +71,3 @@
         types.resolve(self).to_symbol()
     }
 }
-
-impl CppName {
-    pub fn new(namespace: Namespace, ident: Ident) -> Self {
-        Self { namespace, ident }
-    }
-
-    fn iter_all_segments(&self) -> impl Iterator<Item = &Ident> {
-        self.namespace.iter().chain(std::iter::once(&self.ident))
-    }
-
-    fn join(&self, sep: &str) -> String {
-        self.iter_all_segments()
-            .map(|s| s.to_string())
-            .collect::<Vec<_>>()
-            .join(sep)
-    }
-
-    pub fn to_symbol(&self) -> Symbol {
-        Symbol::from_idents(self.iter_all_segments())
-    }
-
-    pub fn to_fully_qualified(&self) -> String {
-        format!("::{}", self.join("::"))
-    }
-}
diff --git a/syntax/symbol.rs b/syntax/symbol.rs
index c849a62..253f57d 100644
--- a/syntax/symbol.rs
+++ b/syntax/symbol.rs
@@ -1,5 +1,5 @@
 use crate::syntax::namespace::Namespace;
-use crate::syntax::CppName;
+use crate::syntax::Pair;
 use proc_macro2::{Ident, TokenStream};
 use quote::ToTokens;
 use std::fmt::{self, Display, Write};
@@ -79,10 +79,10 @@
     }
 }
 
-impl Segment for CppName {
+impl Segment for Pair {
     fn write(&self, symbol: &mut Symbol) {
         self.namespace.write(symbol);
-        self.ident.write(symbol);
+        self.cxx.write(symbol);
     }
 }
 
diff --git a/syntax/types.rs b/syntax/types.rs
index 178da3e..d9d6361 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -2,8 +2,7 @@
 use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
 use crate::syntax::{
-    Api, CppName, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type,
-    TypeAlias,
+    Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type, TypeAlias,
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
@@ -19,7 +18,7 @@
     pub untrusted: Map<&'a Ident, &'a ExternType>,
     pub required_trivial: Map<&'a Ident, TrivialReason<'a>>,
     pub explicit_impls: Set<&'a Impl>,
-    pub resolutions: Map<&'a Ident, &'a CppName>,
+    pub resolutions: Map<&'a Ident, &'a Pair>,
 }
 
 impl<'a> Types<'a> {
@@ -56,7 +55,7 @@
         }
 
         let mut add_resolution = |pair: &'a Pair| {
-            resolutions.insert(&pair.rust, &pair.cxx);
+            resolutions.insert(&pair.rust, pair);
         };
 
         let mut type_names = UnorderedSet::new();
@@ -228,7 +227,7 @@
         false
     }
 
-    pub fn resolve(&self, ident: &ResolvableName) -> &CppName {
+    pub fn resolve(&self, ident: &ResolvableName) -> &Pair {
         self.resolutions
             .get(&ident.rust)
             .expect("Unable to resolve type")